Skip to content
This repository
Browse code

Merge remainder of util.js into effects.js

git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@2647 5ecf4fe2-1ee6-0310-87b1-e25e094e27de
  • Loading branch information...
commit 0453525f8dc67b78a8805ed4b1583c47f723be86 1 parent 8103d37
Sam Stephenson authored October 16, 2005
290  actionpack/lib/action_view/helpers/javascripts/effects.js
@@ -6,6 +6,296 @@
6 6
 // 
7 7
 // See scriptaculous.js for full license.
8 8
 
  9
+Object.debug = function(obj) {
  10
+  var info = [];
  11
+  
  12
+  if(typeof obj in ["string","number"]) {
  13
+    return obj;
  14
+  } else {
  15
+    for(property in obj)
  16
+      if(typeof obj[property]!="function")
  17
+        info.push(property + ' => ' + 
  18
+          (typeof obj[property] == "string" ?
  19
+            '"' + obj[property] + '"' :
  20
+            obj[property]));
  21
+  }
  22
+  
  23
+  return ("'" + obj + "' #" + typeof obj + 
  24
+    ": {" + info.join(", ") + "}");
  25
+}
  26
+
  27
+
  28
+/*--------------------------------------------------------------------------*/
  29
+
  30
+var Builder = {
  31
+  NODEMAP: {
  32
+    AREA: 'map',
  33
+    CAPTION: 'table',
  34
+    COL: 'table',
  35
+    COLGROUP: 'table',
  36
+    LEGEND: 'fieldset',
  37
+    OPTGROUP: 'select',
  38
+    OPTION: 'select',
  39
+    PARAM: 'object',
  40
+    TBODY: 'table',
  41
+    TD: 'table',
  42
+    TFOOT: 'table',
  43
+    TH: 'table',
  44
+    THEAD: 'table',
  45
+    TR: 'table'
  46
+  },
  47
+  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
  48
+  //       due to a Firefox bug
  49
+  node: function(elementName) {
  50
+    elementName = elementName.toUpperCase();
  51
+    
  52
+    // try innerHTML approach
  53
+    var parentTag = this.NODEMAP[elementName] || 'div';
  54
+    var parentElement = document.createElement(parentTag);
  55
+    parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
  56
+    var element = parentElement.firstChild || null;
  57
+      
  58
+    // see if browser added wrapping tags
  59
+    if(element && (element.tagName != elementName))
  60
+      element = element.getElementsByTagName(elementName)[0];
  61
+    
  62
+    // fallback to createElement approach
  63
+    if(!element) element = document.createElement(elementName);
  64
+    
  65
+    // abort if nothing could be created
  66
+    if(!element) return;
  67
+
  68
+    // attributes (or text)
  69
+    if(arguments[1])
  70
+      if(this._isStringOrNumber(arguments[1]) ||
  71
+        (arguments[1] instanceof Array)) {
  72
+          this._children(element, arguments[1]);
  73
+        } else {
  74
+          var attrs = this._attributes(arguments[1]);
  75
+          if(attrs.length) {
  76
+            parentElement.innerHTML = "<" +elementName + " " +
  77
+              attrs + "></" + elementName + ">";
  78
+            element = parentElement.firstChild || null;
  79
+            // workaround firefox 1.0.X bug
  80
+            if(!element) {
  81
+              element = document.createElement(elementName);
  82
+              for(attr in arguments[1]) 
  83
+                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
  84
+            }
  85
+            if(element.tagName != elementName)
  86
+              element = parentElement.getElementsByTagName(elementName)[0];
  87
+            }
  88
+        } 
  89
+
  90
+    // text, or array of children
  91
+    if(arguments[2])
  92
+      this._children(element, arguments[2]);
  93
+
  94
+     return element;
  95
+  },
  96
+  _text: function(text) {
  97
+     return document.createTextNode(text);
  98
+  },
  99
+  _attributes: function(attributes) {
  100
+    var attrs = [];
  101
+    for(attribute in attributes)
  102
+      attrs.push((attribute=='className' ? 'class' : attribute) +
  103
+          '="' + attributes[attribute].toString().escapeHTML() + '"');
  104
+    return attrs.join(" ");
  105
+  },
  106
+  _children: function(element, children) {
  107
+    if(typeof children=='object') { // array can hold nodes and text
  108
+      children.flatten().each( function(e) {
  109
+        if(typeof e=='object')
  110
+          element.appendChild(e)
  111
+        else
  112
+          if(Builder._isStringOrNumber(e))
  113
+            element.appendChild(Builder._text(e));
  114
+      });
  115
+    } else
  116
+      if(Builder._isStringOrNumber(children)) 
  117
+         element.appendChild(Builder._text(children));
  118
+  },
  119
+  _isStringOrNumber: function(param) {
  120
+    return(typeof param=='string' || typeof param=='number');
  121
+  }
  122
+}
  123
+
  124
+/* ------------- element ext -------------- */
  125
+
  126
+// converts rgb() and #xxx to #xxxxxx format,
  127
+// returns self (or first argument) if not convertable
  128
+String.prototype.parseColor = function() {
  129
+  color = "#";
  130
+  if(this.slice(0,4) == "rgb(") {
  131
+    var cols = this.slice(4,this.length-1).split(',');
  132
+    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
  133
+  } else {
  134
+    if(this.slice(0,1) == '#') {
  135
+      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
  136
+      if(this.length==7) color = this.toLowerCase();
  137
+    }
  138
+  }
  139
+  return(color.length==7 ? color : (arguments[0] || this));
  140
+}
  141
+
  142
+Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
  143
+  var children = $(element).childNodes;
  144
+  var text     = "";
  145
+  var classtest = new RegExp("^([^ ]+ )*" + ignoreclass+ "( [^ ]+)*$","i");
  146
+
  147
+  for (var i = 0; i < children.length; i++) {
  148
+    if(children[i].nodeType==3) {
  149
+      text+=children[i].nodeValue;
  150
+    } else {
  151
+      if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
  152
+        text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
  153
+    }
  154
+  }
  155
+
  156
+  return text;
  157
+}
  158
+
  159
+Element.setContentZoom = function(element, percent) {
  160
+  element = $(element);
  161
+  element.style.fontSize = (percent/100) + "em";  
  162
+  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
  163
+}
  164
+
  165
+Element.getOpacity = function(element){
  166
+  var opacity;
  167
+  if (opacity = Element.getStyle(element, "opacity"))
  168
+    return parseFloat(opacity);
  169
+  if (opacity = (Element.getStyle(element, "filter") || '').match(/alpha\(opacity=(.*)\)/))
  170
+    if(opacity[1]) return parseFloat(opacity[1]) / 100;
  171
+  return 1.0;
  172
+}
  173
+
  174
+Element.setOpacity = function(element, value){
  175
+  element= $(element);
  176
+  var els = element.style;
  177
+  if (value == 1){
  178
+    els.opacity = '0.999999';
  179
+    if(/MSIE/.test(navigator.userAgent))
  180
+      els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'');
  181
+  } else {
  182
+    if(value < 0.00001) value = 0;
  183
+    els.opacity = value;
  184
+    if(/MSIE/.test(navigator.userAgent))
  185
+      els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + 
  186
+        "alpha(opacity="+value*100+")";
  187
+  }  
  188
+}
  189
+
  190
+Element.getInlineOpacity = function(element){
  191
+  element= $(element);
  192
+  var op;
  193
+  op = element.style.opacity;
  194
+  if (typeof op != "undefined" && op != "") return op;
  195
+  return "";
  196
+}
  197
+
  198
+Element.setInlineOpacity = function(element, value){
  199
+  element= $(element);
  200
+  var els = element.style;
  201
+  els.opacity = value;
  202
+}
  203
+
  204
+/*--------------------------------------------------------------------------*/
  205
+
  206
+Element.Class = {
  207
+    // Element.toggleClass(element, className) toggles the class being on/off
  208
+    // Element.toggleClass(element, className1, className2) toggles between both classes,
  209
+    //   defaulting to className1 if neither exist
  210
+    toggle: function(element, className) {
  211
+      if(Element.Class.has(element, className)) {
  212
+        Element.Class.remove(element, className);
  213
+        if(arguments.length == 3) Element.Class.add(element, arguments[2]);
  214
+      } else {
  215
+        Element.Class.add(element, className);
  216
+        if(arguments.length == 3) Element.Class.remove(element, arguments[2]);
  217
+      }
  218
+    },
  219
+
  220
+    // gets space-delimited classnames of an element as an array
  221
+    get: function(element) {
  222
+      return $(element).className.split(' ');
  223
+    },
  224
+
  225
+    // functions adapted from original functions by Gavin Kistner
  226
+    remove: function(element) {
  227
+      element = $(element);
  228
+      var removeClasses = arguments;
  229
+      $R(1,arguments.length-1).each( function(index) {
  230
+        element.className = 
  231
+          element.className.split(' ').reject( 
  232
+            function(klass) { return (klass == removeClasses[index]) } ).join(' ');
  233
+      });
  234
+    },
  235
+
  236
+    add: function(element) {
  237
+      element = $(element);
  238
+      for(var i = 1; i < arguments.length; i++) {
  239
+        Element.Class.remove(element, arguments[i]);
  240
+        element.className += (element.className.length > 0 ? ' ' : '') + arguments[i];
  241
+      }
  242
+    },
  243
+
  244
+    // returns true if all given classes exist in said element
  245
+    has: function(element) {
  246
+      element = $(element);
  247
+      if(!element || !element.className) return false;
  248
+      var regEx;
  249
+      for(var i = 1; i < arguments.length; i++) {
  250
+        if((typeof arguments[i] == 'object') && 
  251
+          (arguments[i].constructor == Array)) {
  252
+          for(var j = 0; j < arguments[i].length; j++) {
  253
+            regEx = new RegExp("(^|\\s)" + arguments[i][j] + "(\\s|$)");
  254
+            if(!regEx.test(element.className)) return false;
  255
+          }
  256
+        } else {
  257
+          regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)");
  258
+          if(!regEx.test(element.className)) return false;
  259
+        }
  260
+      }
  261
+      return true;
  262
+    },
  263
+
  264
+    // expects arrays of strings and/or strings as optional paramters
  265
+    // Element.Class.has_any(element, ['classA','classB','classC'], 'classD')
  266
+    has_any: function(element) {
  267
+      element = $(element);
  268
+      if(!element || !element.className) return false;
  269
+      var regEx;
  270
+      for(var i = 1; i < arguments.length; i++) {
  271
+        if((typeof arguments[i] == 'object') && 
  272
+          (arguments[i].constructor == Array)) {
  273
+          for(var j = 0; j < arguments[i].length; j++) {
  274
+            regEx = new RegExp("(^|\\s)" + arguments[i][j] + "(\\s|$)");
  275
+            if(regEx.test(element.className)) return true;
  276
+          }
  277
+        } else {
  278
+          regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)");
  279
+          if(regEx.test(element.className)) return true;
  280
+        }
  281
+      }
  282
+      return false;
  283
+    },
  284
+
  285
+    childrenWith: function(element, className) {
  286
+      var children = $(element).getElementsByTagName('*');
  287
+      var elements = new Array();
  288
+
  289
+      for (var i = 0; i < children.length; i++)
  290
+        if (Element.Class.has(children[i], className))
  291
+          elements.push(children[i]);
  292
+
  293
+      return elements;
  294
+    }
  295
+}
  296
+
  297
+/*--------------------------------------------------------------------------*/
  298
+
9 299
 var Effect = {
10 300
   tagifyText: function(element) {
11 301
     var tagifyStyle = "position:relative";
548  actionpack/lib/action_view/helpers/javascripts/util.js
... ...
@@ -1,548 +0,0 @@
1  
-// Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
2  
-//
3  
-// See scriptaculous.js for full license.
4  
-
5  
-
6  
-Object.debug = function(obj) {
7  
-  var info = [];
8  
-  
9  
-  if(typeof obj in ["string","number"]) {
10  
-    return obj;
11  
-  } else {
12  
-    for(property in obj)
13  
-      if(typeof obj[property]!="function")
14  
-        info.push(property + ' => ' + 
15  
-          (typeof obj[property] == "string" ?
16  
-            '"' + obj[property] + '"' :
17  
-            obj[property]));
18  
-  }
19  
-  
20  
-  return ("'" + obj + "' #" + typeof obj + 
21  
-    ": {" + info.join(", ") + "}");
22  
-}
23  
-
24  
-
25  
-String.prototype.toArray = function() {
26  
-  var results = [];
27  
-  for (var i = 0; i < this.length; i++)
28  
-    results.push(this.charAt(i));
29  
-  return results;
30  
-}
31  
-
32  
-/*--------------------------------------------------------------------------*/
33  
-
34  
-var Builder = {
35  
-  NODEMAP: {
36  
-    AREA: 'map',
37  
-    CAPTION: 'table',
38  
-    COL: 'table',
39  
-    COLGROUP: 'table',
40  
-    LEGEND: 'fieldset',
41  
-    OPTGROUP: 'select',
42  
-    OPTION: 'select',
43  
-    PARAM: 'object',
44  
-    TBODY: 'table',
45  
-    TD: 'table',
46  
-    TFOOT: 'table',
47  
-    TH: 'table',
48  
-    THEAD: 'table',
49  
-    TR: 'table'
50  
-  },
51  
-  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
52  
-  //       due to a Firefox bug
53  
-  node: function(elementName) {
54  
-    elementName = elementName.toUpperCase();
55  
-    
56  
-    // try innerHTML approach
57  
-    var parentTag = this.NODEMAP[elementName] || 'div';
58  
-    var parentElement = document.createElement(parentTag);
59  
-    parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
60  
-    var element = parentElement.firstChild || null;
61  
-      
62  
-    // see if browser added wrapping tags
63  
-    if(element && (element.tagName != elementName))
64  
-      element = element.getElementsByTagName(elementName)[0];
65  
-    
66  
-    // fallback to createElement approach
67  
-    if(!element) element = document.createElement(elementName);
68  
-    
69  
-    // abort if nothing could be created
70  
-    if(!element) return;
71  
-
72  
-    // attributes (or text)
73  
-    if(arguments[1])
74  
-      if(this._isStringOrNumber(arguments[1]) ||
75  
-        (arguments[1] instanceof Array)) {
76  
-          this._children(element, arguments[1]);
77  
-        } else {
78  
-          var attrs = this._attributes(arguments[1]);
79  
-          if(attrs.length) {
80  
-            parentElement.innerHTML = "<" +elementName + " " +
81  
-              attrs + "></" + elementName + ">";
82  
-            element = parentElement.firstChild || null;
83  
-            // workaround firefox 1.0.X bug
84  
-            if(!element) {
85  
-              element = document.createElement(elementName);
86  
-              for(attr in arguments[1]) 
87  
-                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
88  
-            }
89  
-            if(element.tagName != elementName)
90  
-              element = parentElement.getElementsByTagName(elementName)[0];
91  
-            }
92  
-        } 
93  
-
94  
-    // text, or array of children
95  
-    if(arguments[2])
96  
-      this._children(element, arguments[2]);
97  
-
98  
-     return element;
99  
-  },
100  
-  _text: function(text) {
101  
-     return document.createTextNode(text);
102  
-  },
103  
-  _attributes: function(attributes) {
104  
-    var attrs = [];
105  
-    for(attribute in attributes)
106  
-      attrs.push((attribute=='className' ? 'class' : attribute) +
107  
-          '="' + attributes[attribute].toString().escapeHTML() + '"');
108  
-    return attrs.join(" ");
109  
-  },
110  
-  _children: function(element, children) {
111  
-    if(typeof children=='object') { // array can hold nodes and text
112  
-      children.flatten().each( function(e) {
113  
-        if(typeof e=='object')
114  
-          element.appendChild(e)
115  
-        else
116  
-          if(Builder._isStringOrNumber(e))
117  
-            element.appendChild(Builder._text(e));
118  
-      });
119  
-    } else
120  
-      if(Builder._isStringOrNumber(children)) 
121  
-         element.appendChild(Builder._text(children));
122  
-  },
123  
-  _isStringOrNumber: function(param) {
124  
-    return(typeof param=='string' || typeof param=='number');
125  
-  }
126  
-}
127  
-
128  
-/* ------------- element ext -------------- */
129  
-
130  
-// adapted from http://dhtmlkitchen.com/learn/js/setstyle/index4.jsp
131  
-// note: Safari return null on elements with display:none; see http://bugzilla.opendarwin.org/show_bug.cgi?id=4125
132  
-// instead of "auto" values returns null so it's easier to use with || constructs
133  
-
134  
-String.prototype.camelize = function() {
135  
-  var oStringList = this.split('-');
136  
-  if(oStringList.length == 1)    
137  
-    return oStringList[0];
138  
-  var ret = this.indexOf("-") == 0 ? 
139  
-    oStringList[0].charAt(0).toUpperCase() + oStringList[0].substring(1) : oStringList[0];
140  
-  for(var i = 1, len = oStringList.length; i < len; i++){
141  
-    var s = oStringList[i];
142  
-    ret += s.charAt(0).toUpperCase() + s.substring(1)
143  
-  }
144  
-  return ret;
145  
-}
146  
-
147  
-Element.getStyle = function(element, style) {
148  
-  element = $(element);
149  
-  var value = element.style[style.camelize()];
150  
-  if(!value)
151  
-    if(document.defaultView && document.defaultView.getComputedStyle) {
152  
-      var css = document.defaultView.getComputedStyle(element, null);
153  
-      value = (css!=null) ? css.getPropertyValue(style) : null;
154  
-    } else if(element.currentStyle) {
155  
-      value = element.currentStyle[style.camelize()];
156  
-    }
157  
-  
158  
-  // If top, left, bottom, or right values have been queried, return "auto" for consistency resaons 
159  
-  // if position is "static", as Opera (and others?) returns the pixel values relative to root element 
160  
-  // (or positioning context?)
161  
-  if (window.opera && (style == "left" || style == "top" || style == "right" || style == "bottom"))
162  
-    if (Element.getStyle(element, "position") == "static") value = "auto";
163  
-    
164  
-  if(value=='auto') value = null;
165  
-  return value;
166  
-}
167  
-
168  
-// converts rgb() and #xxx to #xxxxxx format,
169  
-// returns self (or first argument) if not convertable
170  
-String.prototype.parseColor = function() {
171  
-  color = "#";
172  
-  if(this.slice(0,4) == "rgb(") {
173  
-    var cols = this.slice(4,this.length-1).split(',');
174  
-    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
175  
-  } else {
176  
-    if(this.slice(0,1) == '#') {
177  
-      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
178  
-      if(this.length==7) color = this.toLowerCase();
179  
-    }
180  
-  }
181  
-  return(color.length==7 ? color : (arguments[0] || this));
182  
-}
183  
-
184  
-Element.makePositioned = function(element) {
185  
-  element = $(element);
186  
-  var pos = Element.getStyle(element, 'position');
187  
-  if(pos =='static' || !pos) {
188  
-    element._madePositioned = true;
189  
-    element.style.position = "relative";
190  
-    // Opera returns the offset relative to the positioning context, when an element is position relative 
191  
-    // but top and left have not been defined
192  
-    if (window.opera){
193  
-      element.style.top = 0;
194  
-      element.style.left = 0;
195  
-    }  
196  
-  }
197  
-}
198  
-  
199  
-Element.undoPositioned = function(element) {
200  
-  element = $(element);
201  
-  if(typeof element._madePositioned != "undefined"){
202  
-    element._madePositioned = undefined;
203  
-    element.style.position = "";
204  
-    element.style.top = "";
205  
-    element.style.left = "";
206  
-    element.style.bottom = "";
207  
-    element.style.right = "";	  
208  
-  }
209  
-}
210  
-
211  
-Element.makeClipping = function(element) {
212  
-  element = $(element);
213  
-  if (typeof element._overflow != 'undefined') return;
214  
-  element._overflow = element.style.overflow;
215  
-  if((Element.getStyle(element, 'overflow') || 'visible') != 'hidden') element.style.overflow = 'hidden';
216  
-}
217  
-
218  
-Element.undoClipping = function(element) {
219  
-  element = $(element);
220  
-  if (typeof element._overflow == 'undefined') return;
221  
-  element.style.overflow = element._overflow;
222  
-  element._overflow = undefined;
223  
-}
224  
-
225  
-Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
226  
-  var children = $(element).childNodes;
227  
-  var text     = "";
228  
-  var classtest = new RegExp("^([^ ]+ )*" + ignoreclass+ "( [^ ]+)*$","i");
229  
-
230  
-  for (var i = 0; i < children.length; i++) {
231  
-    if(children[i].nodeType==3) {
232  
-      text+=children[i].nodeValue;
233  
-    } else {
234  
-      if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
235  
-        text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
236  
-    }
237  
-  }
238  
-
239  
-  return text;
240  
-}
241  
-
242  
-Element.setContentZoom = function(element, percent) {
243  
-  element = $(element);
244  
-  element.style.fontSize = (percent/100) + "em";  
245  
-  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
246  
-}
247  
-
248  
-Element.getOpacity = function(element){
249  
-  var opacity;
250  
-  if (opacity = Element.getStyle(element, "opacity"))
251  
-    return parseFloat(opacity);
252  
-  if (opacity = (Element.getStyle(element, "filter") || '').match(/alpha\(opacity=(.*)\)/))
253  
-    if(opacity[1]) return parseFloat(opacity[1]) / 100;
254  
-  return 1.0;
255  
-}
256  
-
257  
-Element.setOpacity = function(element, value){
258  
-  element= $(element);
259  
-  var els = element.style;
260  
-  if (value == 1){
261  
-    els.opacity = '0.999999';
262  
-    if(/MSIE/.test(navigator.userAgent))
263  
-      els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'');
264  
-  } else {
265  
-    if(value < 0.00001) value = 0;
266  
-    els.opacity = value;
267  
-    if(/MSIE/.test(navigator.userAgent))
268  
-      els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + 
269  
-        "alpha(opacity="+value*100+")";
270  
-  }  
271  
-}
272  
-
273  
-Element.getInlineOpacity = function(element){
274  
-  element= $(element);
275  
-  var op;
276  
-  op = element.style.opacity;
277  
-  if (typeof op != "undefined" && op != "") return op;
278  
-  return "";
279  
-}
280  
-
281  
-Element.setInlineOpacity = function(element, value){
282  
-  element= $(element);
283  
-  var els = element.style;
284  
-  els.opacity = value;
285  
-}
286  
-
287  
-Element.getDimensions = function(element){
288  
-  element = $(element);
289  
-  // All *Width and *Height properties give 0 on elements with display "none", 
290  
-  // so enable the element temporarily
291  
-  if (Element.getStyle(element,'display') == "none"){
292  
-    var els = element.style;
293  
-    var originalVisibility = els.visibility;
294  
-    var originalPosition = els.position;
295  
-    els.visibility = "hidden";
296  
-    els.position = "absolute";
297  
-    els.display = "";
298  
-    var originalWidth = element.clientWidth;
299  
-    var originalHeight = element.clientHeight;
300  
-    els.display = "none";
301  
-    els.position = originalPosition;
302  
-    els.visibility = originalVisibility;
303  
-    return {width: originalWidth, height: originalHeight};    
304  
-  }
305  
-  
306  
-  return {width: element.offsetWidth, height: element.offsetHeight};
307  
-} 
308  
-
309  
-/*--------------------------------------------------------------------------*/
310  
-
311  
-Position.positionedOffset = function(element) {
312  
-  var valueT = 0, valueL = 0;
313  
-  do {
314  
-    valueT += element.offsetTop  || 0;
315  
-    valueL += element.offsetLeft || 0;
316  
-    element = element.offsetParent;
317  
-    if (element) {
318  
-      p = Element.getStyle(element,'position');
319  
-      if(p == 'relative' || p == 'absolute') break;
320  
-    }
321  
-  } while (element);
322  
-  return [valueL, valueT];
323  
-}
324  
-
325  
-// Safari returns margins on body which is incorrect if the child is absolutely positioned.
326  
-// for performance reasons, we create a specialized version of Position.cumulativeOffset for
327  
-// KHTML/WebKit only
328  
-
329  
-if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)) {
330  
-  Position.cumulativeOffset = function(element) {
331  
-    var valueT = 0, valueL = 0;
332  
-    do {
333  
-      valueT += element.offsetTop  || 0;
334  
-      valueL += element.offsetLeft || 0;
335  
-      
336  
-      if (element.offsetParent==document.body) 
337  
-        if (Element.getStyle(element,'position')=='absolute') break;
338  
-        
339  
-      element = element.offsetParent;
340  
-    } while (element);
341  
-    return [valueL, valueT];
342  
-  }
343  
-}
344  
-
345  
-Position.page = function(forElement) {
346  
-  var valueT = 0, valueL = 0;
347  
-
348  
-  var element = forElement;
349  
-  do {
350  
-    valueT += element.offsetTop  || 0;
351  
-    valueL += element.offsetLeft || 0;
352  
-
353  
-    // Safari fix
354  
-    if (element.offsetParent==document.body)
355  
-      if (Element.getStyle(element,'position')=='absolute') break;
356  
-      
357  
-  } while (element = element.offsetParent);
358  
-
359  
-  element = forElement;
360  
-  do {
361  
-    valueT -= element.scrollTop  || 0;
362  
-    valueL -= element.scrollLeft || 0;    
363  
-  } while (element = element.parentNode);
364  
-
365  
-  return [valueL, valueT];
366  
-}
367  
-
368  
-// elements with display:none don't return an offsetParent, 
369  
-// fall back to  manual calculation
370  
-Position.offsetParent = function(element) {
371  
-  if(element.offsetParent) return element.offsetParent;
372  
-  if(element == document.body) return element;
373  
-  
374  
-  while ((element = element.parentNode) && element != document.body)
375  
-    if (Element.getStyle(element,'position')!='static')
376  
-      return element;
377  
-  
378  
-  return document.body;
379  
-}
380  
-
381  
-Position.clone = function(source, target) {
382  
-  var options = Object.extend({
383  
-    setLeft:    true,
384  
-    setTop:     true,
385  
-    setWidth:   true,
386  
-    setHeight:  true,
387  
-    offsetTop:  0,
388  
-    offsetLeft: 0
389  
-  }, arguments[2] || {})
390  
-  
391  
-  // find page position of source
392  
-  source = $(source);
393  
-  var p = Position.page(source);
394  
-
395  
-  // find coordinate system to use
396  
-  target = $(target);
397  
-  var delta = [0, 0];
398  
-  var parent = null;
399  
-  // delta [0,0] will do fine with position: fixed elements, 
400  
-  // position:absolute needs offsetParent deltas
401  
-  if (Element.getStyle(target,'position') == 'absolute') {
402  
-    parent = Position.offsetParent(target);
403  
-    delta = Position.page(parent);
404  
-  }
405  
-  
406  
-  // correct by body offsets (fixes Safari)
407  
-  if (parent==document.body) {
408  
-    delta[0] -= document.body.offsetLeft;
409  
-    delta[1] -= document.body.offsetTop; 
410  
-  }
411  
-
412  
-  // set position
413  
-  if(options.setLeft)   target.style.left  = (p[0] - delta[0] + options.offsetLeft) + "px";
414  
-  if(options.setTop)    target.style.top   = (p[1] - delta[1] + options.offsetTop) + "px";
415  
-  if(options.setWidth)  target.style.width = source.offsetWidth + "px";
416  
-  if(options.setHeight) target.style.height = source.offsetHeight + "px";
417  
-}
418  
-
419  
-Position.absolutize = function(element) {
420  
-  element = $(element);
421  
-  if(element.style.position=='absolute') return;
422  
-  Position.prepare();
423  
-
424  
-  var offsets = Position.positionedOffset(element);
425  
-  var top     = offsets[1];
426  
-  var left    = offsets[0];
427  
-  var width   = element.clientWidth;
428  
-  var height  = element.clientHeight;
429  
-
430  
-  element._originalLeft   = left - parseFloat(element.style.left  || 0);
431  
-  element._originalTop    = top  - parseFloat(element.style.top || 0);
432  
-  element._originalWidth  = element.style.width;
433  
-  element._originalHeight = element.style.height;
434  
-
435  
-  element.style.position = 'absolute';
436  
-  element.style.top    = top + 'px';;
437  
-  element.style.left   = left + 'px';;
438  
-  element.style.width  = width + 'px';;
439  
-  element.style.height = height + 'px';;
440  
-}
441  
-
442  
-Position.relativize = function(element) {
443  
-  element = $(element);
444  
-  if(element.style.position=='relative') return;
445  
-  Position.prepare();
446  
-
447  
-  element.style.position = 'relative';
448  
-  var top  = parseFloat(element.style.top  || 0) - (element._originalTop || 0);
449  
-  var left = parseFloat(element.style.left || 0) - (element._originalLeft || 0);
450  
-
451  
-  element.style.top    = top + 'px';
452  
-  element.style.left   = left + 'px';
453  
-  element.style.height = element._originalHeight;
454  
-  element.style.width  = element._originalWidth;
455  
-}
456  
-
457  
-/*--------------------------------------------------------------------------*/
458  
-
459  
-Element.Class = {
460  
-    // Element.toggleClass(element, className) toggles the class being on/off
461  
-    // Element.toggleClass(element, className1, className2) toggles between both classes,
462  
-    //   defaulting to className1 if neither exist
463  
-    toggle: function(element, className) {
464  
-      if(Element.Class.has(element, className)) {
465  
-        Element.Class.remove(element, className);
466  
-        if(arguments.length == 3) Element.Class.add(element, arguments[2]);
467  
-      } else {
468  
-        Element.Class.add(element, className);
469  
-        if(arguments.length == 3) Element.Class.remove(element, arguments[2]);
470  
-      }
471  
-    },
472  
-
473  
-    // gets space-delimited classnames of an element as an array
474  
-    get: function(element) {
475  
-      return $(element).className.split(' ');
476  
-    },
477  
-
478  
-    // functions adapted from original functions by Gavin Kistner
479  
-    remove: function(element) {
480  
-      element = $(element);
481  
-      var removeClasses = arguments;
482  
-      $R(1,arguments.length-1).each( function(index) {
483  
-        element.className = 
484  
-          element.className.split(' ').reject( 
485  
-            function(klass) { return (klass == removeClasses[index]) } ).join(' ');
486  
-      });
487  
-    },
488  
-
489  
-    add: function(element) {
490  
-      element = $(element);
491  
-      for(var i = 1; i < arguments.length; i++) {
492  
-        Element.Class.remove(element, arguments[i]);
493  
-        element.className += (element.className.length > 0 ? ' ' : '') + arguments[i];
494  
-      }
495  
-    },
496  
-
497  
-    // returns true if all given classes exist in said element
498  
-    has: function(element) {
499  
-      element = $(element);
500  
-      if(!element || !element.className) return false;
501  
-      var regEx;
502  
-      for(var i = 1; i < arguments.length; i++) {
503  
-        if((typeof arguments[i] == 'object') && 
504  
-          (arguments[i].constructor == Array)) {
505  
-          for(var j = 0; j < arguments[i].length; j++) {
506  
-            regEx = new RegExp("(^|\\s)" + arguments[i][j] + "(\\s|$)");
507  
-            if(!regEx.test(element.className)) return false;
508  
-          }
509  
-        } else {
510  
-          regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)");
511  
-          if(!regEx.test(element.className)) return false;
512  
-        }
513  
-      }
514  
-      return true;
515  
-    },
516  
-
517  
-    // expects arrays of strings and/or strings as optional paramters
518  
-    // Element.Class.has_any(element, ['classA','classB','classC'], 'classD')
519  
-    has_any: function(element) {
520  
-      element = $(element);
521  
-      if(!element || !element.className) return false;
522  
-      var regEx;
523  
-      for(var i = 1; i < arguments.length; i++) {
524  
-        if((typeof arguments[i] == 'object') && 
525  
-          (arguments[i].constructor == Array)) {
526  
-          for(var j = 0; j < arguments[i].length; j++) {
527  
-            regEx = new RegExp("(^|\\s)" + arguments[i][j] + "(\\s|$)");
528  
-            if(regEx.test(element.className)) return true;
529  
-          }
530  
-        } else {
531  
-          regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)");
532  
-          if(regEx.test(element.className)) return true;
533  
-        }
534  
-      }
535  
-      return false;
536  
-    },
537  
-
538  
-    childrenWith: function(element, className) {
539  
-      var children = $(element).getElementsByTagName('*');
540  
-      var elements = new Array();
541  
-
542  
-      for (var i = 0; i < children.length; i++)
543  
-        if (Element.Class.has(children[i], className))
544  
-          elements.push(children[i]);
545  
-
546  
-      return elements;
547  
-    }
548  
-}
4  railties/Rakefile
@@ -37,7 +37,7 @@ LOG_FILES    = %w( server.log development.log test.log production.log )
37 37
 HTML_FILES   = %w( 404.html 500.html index.html robots.txt favicon.ico 
38 38
                    javascripts/prototype.js javascripts/scriptaculous.js
39 39
                    javascripts/effects.js javascripts/dragdrop.js javascripts/controls.js
40  
-                   javascripts/util.js javascripts/slider.js )
  40
+                   javascripts/slider.js )
41 41
 BIN_FILES    = %w( breakpointer console destroy generate performance/benchmarker performance/profiler process/reaper process/spawner process/spinner runner server )
42 42
 
43 43
 VENDOR_LIBS = %w( actionpack activerecord actionmailer activesupport actionwebservice railties )
@@ -72,7 +72,7 @@ end
72 72
 
73 73
 desc "Updates railties to the latest version of the javascript spinoffs"
74 74
 task :update_js do
75  
-  for js in %w( prototype controls dragdrop effects util slider )
  75
+  for js in %w( prototype controls dragdrop effects slider )
76 76
     rm "html/javascripts/#{js}.js"
77 77
     cp "./../actionpack/lib/action_view/helpers/javascripts/#{js}.js", "html/javascripts"
78 78
   end
290  railties/html/javascripts/effects.js
@@ -6,6 +6,296 @@
6 6
 // 
7 7
 // See scriptaculous.js for full license.
8 8
 
  9
+Object.debug = function(obj) {
  10
+  var info = [];
  11
+  
  12
+  if(typeof obj in ["string","number"]) {
  13
+    return obj;
  14
+  } else {
  15
+    for(property in obj)
  16
+      if(typeof obj[property]!="function")
  17
+        info.push(property + ' => ' + 
  18
+          (typeof obj[property] == "string" ?
  19
+            '"' + obj[property] + '"' :
  20
+            obj[property]));
  21
+  }
  22
+  
  23
+  return ("'" + obj + "' #" + typeof obj + 
  24
+    ": {" + info.join(", ") + "}");
  25
+}
  26
+
  27
+
  28
+/*--------------------------------------------------------------------------*/
  29
+
  30
+var Builder = {
  31
+  NODEMAP: {
  32
+    AREA: 'map',
  33
+    CAPTION: 'table',
  34
+    COL: 'table',
  35
+    COLGROUP: 'table',
  36
+    LEGEND: 'fieldset',
  37
+    OPTGROUP: 'select',
  38
+    OPTION: 'select',
  39
+    PARAM: 'object',
  40
+    TBODY: 'table',
  41
+    TD: 'table',
  42
+    TFOOT: 'table',
  43
+    TH: 'table',
  44
+    THEAD: 'table',
  45
+    TR: 'table'
  46
+  },
  47
+  // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
  48
+  //       due to a Firefox bug
  49
+  node: function(elementName) {
  50
+    elementName = elementName.toUpperCase();
  51
+    
  52
+    // try innerHTML approach
  53
+    var parentTag = this.NODEMAP[elementName] || 'div';
  54
+    var parentElement = document.createElement(parentTag);
  55
+    parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
  56
+    var element = parentElement.firstChild || null;
  57
+      
  58
+    // see if browser added wrapping tags
  59
+    if(element && (element.tagName != elementName))
  60
+      element = element.getElementsByTagName(elementName)[0];
  61
+    
  62
+    // fallback to createElement approach
  63
+    if(!element) element = document.createElement(elementName);
  64
+    
  65
+    // abort if nothing could be created
  66
+    if(!element) return;
  67
+
  68
+    // attributes (or text)
  69
+    if(arguments[1])
  70
+      if(this._isStringOrNumber(arguments[1]) ||
  71
+        (arguments[1] instanceof Array)) {
  72
+          this._children(element, arguments[1]);
  73
+        } else {
  74
+          var attrs = this._attributes(arguments[1]);
  75
+          if(attrs.length) {
  76
+            parentElement.innerHTML = "<" +elementName + " " +
  77
+              attrs + "></" + elementName + ">";
  78
+            element = parentElement.firstChild || null;
  79
+            // workaround firefox 1.0.X bug
  80
+            if(!element) {
  81
+              element = document.createElement(elementName);
  82
+              for(attr in arguments[1]) 
  83
+                element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
  84
+            }
  85
+            if(element.tagName != elementName)
  86
+              element = parentElement.getElementsByTagName(elementName)[0];
  87
+            }
  88
+        } 
  89
+
  90
+    // text, or array of children
  91
+    if(arguments[2])
  92
+      this._children(element, arguments[2]);
  93
+
  94
+     return element;
  95
+  },
  96
+  _text: function(text) {
  97
+     return document.createTextNode(text);
  98
+  },
  99
+  _attributes: function(attributes) {
  100
+    var attrs = [];
  101
+    for(attribute in attributes)
  102
+      attrs.push((attribute=='className' ? 'class' : attribute) +
  103
+          '="' + attributes[attribute].toString().escapeHTML() + '"');
  104
+    return attrs.join(" ");
  105
+  },
  106
+  _children: function(element, children) {
  107
+    if(typeof children=='object') { // array can hold nodes and text
  108
+      children.flatten().each( function(e) {
  109
+        if(typeof e=='object')
  110
+          element.appendChild(e)
  111
+        else
  112
+          if(Builder._isStringOrNumber(e))
  113
+            element.appendChild(Builder._text(e));
  114
+      });
  115
+    } else
  116
+      if(Builder._isStringOrNumber(children)) 
  117
+         element.appendChild(Builder._text(children));
  118
+  },
  119
+  _isStringOrNumber: function(param) {
  120
+    return(typeof param=='string' || typeof param=='number');
  121
+  }
  122
+}
  123
+
  124
+/* ------------- element ext -------------- */
  125
+
  126
+// converts rgb() and #xxx to #xxxxxx format,
  127
+// returns self (or first argument) if not convertable
  128
+String.prototype.parseColor = function() {
  129
+  color = "#";
  130
+  if(this.slice(0,4) == "rgb(") {
  131
+    var cols = this.slice(4,this.length-1).split(',');
  132
+    var i=0; do { color += parseInt(cols[i]).toColorPart() } while (++i<3);
  133
+  } else {
  134
+    if(this.slice(0,1) == '#') {
  135
+      if(this.length==4) for(var i=1;i<4;i++) color += (this.charAt(i) + this.charAt(i)).toLowerCase();
  136
+      if(this.length==7) color = this.toLowerCase();
  137
+    }
  138
+  }
  139
+  return(color.length==7 ? color : (arguments[0] || this));
  140
+}
  141
+
  142
+Element.collectTextNodesIgnoreClass = function(element, ignoreclass) {
  143
+  var children = $(element).childNodes;
  144
+  var text     = "";
  145
+  var classtest = new RegExp("^([^ ]+ )*" + ignoreclass+ "( [^ ]+)*$","i");
  146
+
  147
+  for (var i = 0; i < children.length; i++) {
  148
+    if(children[i].nodeType==3) {
  149
+      text+=children[i].nodeValue;
  150
+    } else {
  151
+      if((!children[i].className.match(classtest)) && children[i].hasChildNodes())
  152
+        text += Element.collectTextNodesIgnoreClass(children[i], ignoreclass);
  153
+    }
  154
+  }
  155
+
  156
+  return text;
  157
+}
  158
+
  159
+Element.setContentZoom = function(element, percent) {
  160
+  element = $(element);
  161
+  element.style.fontSize = (percent/100) + "em";  
  162
+  if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0);
  163
+}
  164
+
  165
+Element.getOpacity = function(element){
  166
+  var opacity;
  167
+  if (opacity = Element.getStyle(element, "opacity"))
  168
+    return parseFloat(opacity);
  169
+  if (opacity = (Element.getStyle(element, "filter") || '').match(/alpha\(opacity=(.*)\)/))
  170
+    if(opacity[1]) return parseFloat(opacity[1]) / 100;
  171
+  return 1.0;
  172
+}
  173
+
  174
+Element.setOpacity = function(element, value){
  175
+  element= $(element);
  176
+  var els = element.style;
  177
+  if (value == 1){
  178
+    els.opacity = '0.999999';
  179
+    if(/MSIE/.test(navigator.userAgent))
  180
+      els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'');
  181
+  } else {
  182
+    if(value < 0.00001) value = 0;
  183
+    els.opacity = value;
  184
+    if(/MSIE/.test(navigator.userAgent))
  185
+      els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') + 
  186
+        "alpha(opacity="+value*100+")";
  187
+  }  
  188
+}
  189
+
  190
+Element.getInlineOpacity = function(element){
  191
+  element= $(element);
  192
+  var op;
  193
+  op = element.style.opacity;
  194
+  if (typeof op != "undefined" && op != "") return op;
  195
+  return "";
  196
+}
  197
+
  198
+Element.setInlineOpacity = function(element, value){
  199
+  element= $(element);
  200
+  var els = element.style;
  201
+  els.opacity = value;
  202
+}
  203
+
  204
+/*--------------------------------------------------------------------------*/
  205
+
  206
+Element.Class = {
  207
+    // Element.toggleClass(element, className) toggles the class being on/off
  208
+    // Element.toggleClass(element, className1, className2) toggles between both classes,
  209
+    //   defaulting to className1 if neither exist
  210
+    toggle: function(element, className) {
  211
+      if(Element.Class.has(element, className)) {
  212
+        Element.Class.remove(element, className);
  213
+        if(arguments.length == 3) Element.Class.add(element, arguments[2]);
  214
+      } else {
  215
+        Element.Class.add(element, className);
  216
+        if(arguments.length == 3) Element.Class.remove(element, arguments[2]);
  217
+      }
  218
+    },
  219
+