aboutsummaryrefslogtreecommitdiffstats
path: root/railties
diff options
context:
space:
mode:
Diffstat (limited to 'railties')
-rw-r--r--railties/CHANGELOG2
-rw-r--r--railties/Rakefile2
-rw-r--r--railties/html/javascripts/controls.js113
-rw-r--r--railties/html/javascripts/dragdrop.js32
-rw-r--r--railties/html/javascripts/effects.js99
-rw-r--r--railties/html/javascripts/prototype.js339
-rw-r--r--railties/html/javascripts/util.js141
-rw-r--r--railties/lib/rails_generator/generators/applications/app/app_generator.rb11
8 files changed, 458 insertions, 281 deletions
diff --git a/railties/CHANGELOG b/railties/CHANGELOG
index e74bbf1df9..259eb44e10 100644
--- a/railties/CHANGELOG
+++ b/railties/CHANGELOG
@@ -1,5 +1,7 @@
*SVN*
+* Update Prototype to V1.4.0_pre11, script.aculo.us to [2502] and fix the rails generator to include the new .js files [Thomas Fuchs]
+
* Make the generator skip a file if it already exists and is identical to the new file.
* Add experimental plugin support #2335
diff --git a/railties/Rakefile b/railties/Rakefile
index bf3ca418de..7724c77c24 100644
--- a/railties/Rakefile
+++ b/railties/Rakefile
@@ -70,7 +70,7 @@ end
desc "Updates railties to the latest version of the javascript spinoffs"
task :update_js do
- for js in %w( prototype controls dragdrop effects )
+ for js in %w( prototype controls dragdrop effects util slider )
rm "html/javascripts/#{js}.js"
cp "./../actionpack/lib/action_view/helpers/javascripts/#{js}.js", "html/javascripts"
end
diff --git a/railties/html/javascripts/controls.js b/railties/html/javascripts/controls.js
index 77046d9c35..a7436bcf17 100644
--- a/railties/html/javascripts/controls.js
+++ b/railties/html/javascripts/controls.js
@@ -60,7 +60,7 @@ Autocompleter.Base.prototype = {
update.style.position = 'absolute';
Position.clone(element, update, {setHeight: false, offsetTop: element.offsetHeight});
}
- new Effect.Appear(update,{duration:0.15});
+ Effect.Appear(update,{duration:0.15});
};
this.options.onHide = this.options.onHide ||
function(element, update){ new Effect.Fade(update,{duration:0.15}) };
@@ -87,15 +87,18 @@ Autocompleter.Base.prototype = {
'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
this.iefix = $(this.update.id+'_iefix');
}
- if(this.iefix) {
- Position.clone(this.update, this.iefix);
- this.iefix.style.zIndex = 1;
- this.update.style.zIndex = 2;
- Element.show(this.iefix);
- }
+ if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50);
+ },
+
+ fixIEOverlapping: function() {
+ Position.clone(this.update, this.iefix);
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ Element.show(this.iefix);
},
hide: function() {
+ this.stopIndicator();
if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update);
if(this.iefix) Element.hide(this.iefix);
},
@@ -186,7 +189,7 @@ Autocompleter.Base.prototype = {
markPrevious: function() {
if(this.index > 0) this.index--
- else this.index = this.entryCcount-1;
+ else this.index = this.entryCount-1;
},
markNext: function() {
@@ -420,20 +423,7 @@ Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), {
// AJAX in-place editor
//
-// The constructor takes three parameters. The first is the element
-// that should support in-place editing. The second is the url to submit
-// the changed value to. The server should respond with the updated
-// value (the server might have post-processed it or validation might
-// have prevented it from changing). The third is a hash of options.
-//
-// Supported options are (all are optional and have sensible defaults):
-// - okText - The text of the submit button that submits the changed value
-// to the server (default: "ok")
-// - cancelText - The text of the link that cancels editing (default: "cancel")
-// - savingText - The text being displayed as the AJAX engine communicates
-// with the server (default: "Saving...")
-// - formId - The id given to the <form> element
-// (default: the id of the element to edit plus '-inplaceeditor')
+// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
Ajax.InPlaceEditor = Class.create();
Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99";
@@ -461,6 +451,7 @@ Ajax.InPlaceEditor.prototype = {
handleLineBreaks: true,
loadingText: 'Loading...',
savingClassName: 'inplaceeditor-saving',
+ loadingClassName: 'inplaceeditor-loading',
formClassName: 'inplaceeditor-form',
highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
highlightendcolor: "#FFFFFF",
@@ -508,7 +499,7 @@ Ajax.InPlaceEditor.prototype = {
Element.hide(this.options.externalControl);
}
Element.hide(this.element);
- this.form = this.getForm();
+ this.createForm();
this.element.parentNode.insertBefore(this.form, this.element);
Field.focus(this.editField);
// stop the event to avoid a page refresh in Safari
@@ -516,30 +507,29 @@ Ajax.InPlaceEditor.prototype = {
Event.stop(arguments[0]);
}
},
- getForm: function() {
- form = document.createElement("form");
- form.id = this.options.formId;
- Element.addClassName(form, this.options.formClassName)
- form.onsubmit = this.onSubmit.bind(this);
+ createForm: function() {
+ this.form = document.createElement("form");
+ this.form.id = this.options.formId;
+ Element.addClassName(this.form, this.options.formClassName)
+ this.form.onsubmit = this.onSubmit.bind(this);
- this.createEditField(form);
+ this.createEditField();
if (this.options.textarea) {
var br = document.createElement("br");
- form.appendChild(br);
+ this.form.appendChild(br);
}
okButton = document.createElement("input");
okButton.type = "submit";
okButton.value = this.options.okText;
- form.appendChild(okButton);
+ this.form.appendChild(okButton);
cancelLink = document.createElement("a");
cancelLink.href = "#";
cancelLink.appendChild(document.createTextNode(this.options.cancelText));
cancelLink.onclick = this.onclickCancel.bind(this);
- form.appendChild(cancelLink);
- return form;
+ this.form.appendChild(cancelLink);
},
hasHTMLLineBreaks: function(string) {
if (!this.options.handleLineBreaks) return false;
@@ -548,49 +538,57 @@ Ajax.InPlaceEditor.prototype = {
convertHTMLLineBreaks: function(string) {
return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, "");
},
- createEditField: function(form) {
- if (this.options.rows == 1 && !this.hasHTMLLineBreaks(this.getText())) {
+ createEditField: function() {
+ var text;
+ if(this.options.loadTextURL) {
+ text = this.options.loadingText;
+ } else {
+ text = this.getText();
+ }
+
+ if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
this.options.textarea = false;
var textField = document.createElement("input");
textField.type = "text";
textField.name = "value";
- textField.value = this.getText();
+ textField.value = text;
textField.style.backgroundColor = this.options.highlightcolor;
var size = this.options.size || this.options.cols || 0;
- if (size != 0)
- textField.size = size;
- form.appendChild(textField);
+ if (size != 0) textField.size = size;
this.editField = textField;
} else {
this.options.textarea = true;
var textArea = document.createElement("textarea");
textArea.name = "value";
- textArea.value = this.convertHTMLLineBreaks(this.getText());
+ textArea.value = this.convertHTMLLineBreaks(text);
textArea.rows = this.options.rows;
textArea.cols = this.options.cols || 40;
- form.appendChild(textArea);
this.editField = textArea;
}
- },
- getText: function() {
- if (this.options.loadTextURL) {
+
+ if(this.options.loadTextURL) {
this.loadExternalText();
- return this.options.loadingText;
- } else {
- return this.element.innerHTML;
}
+ this.form.appendChild(this.editField);
+ },
+ getText: function() {
+ return this.element.innerHTML;
},
loadExternalText: function() {
+ Element.addClassName(this.form, this.options.loadingClassName);
+ this.editField.disabled = true;
new Ajax.Request(
this.options.loadTextURL,
- {
+ Object.extend({
asynchronous: true,
onComplete: this.onLoadedExternalText.bind(this)
- }
+ }, this.options.ajaxOptions)
);
},
onLoadedExternalText: function(transport) {
- this.form.value.value = transport.responseText.stripTags();
+ Element.removeClassName(this.form, this.options.loadingClassName);
+ this.editField.disabled = false;
+ this.editField.value = transport.responseText.stripTags();
},
onclickCancel: function() {
this.onComplete();
@@ -606,7 +604,15 @@ Ajax.InPlaceEditor.prototype = {
return false;
},
onSubmit: function() {
- this.saving = true;
+ // onLoading resets these so we need to save them away for the Ajax call
+ var form = this.form;
+ var value = this.editField.value;
+
+ // do this first, sometimes the ajax call returns before we get a chance to switch on Saving...
+ // which means this will actually switch on Saving... *after* we've left edit mode causing Saving...
+ // to be displayed indefinitely
+ this.onLoading();
+
new Ajax.Updater(
{
success: this.element,
@@ -615,12 +621,11 @@ Ajax.InPlaceEditor.prototype = {
},
this.url,
Object.extend({
- parameters: this.options.callback(this.form, this.editField.value),
+ parameters: this.options.callback(form, value),
onComplete: this.onComplete.bind(this),
onFailure: this.onFailure.bind(this)
}, this.options.ajaxOptions)
);
- this.onLoading();
// stop the event to avoid a page refresh in Safari
if (arguments.length > 1) {
Event.stop(arguments[0]);
@@ -642,7 +647,7 @@ Ajax.InPlaceEditor.prototype = {
},
removeForm: function() {
if(this.form) {
- Element.remove(this.form);
+ if (this.form.parentNode) Element.remove(this.form);
this.form = null;
}
},
diff --git a/railties/html/javascripts/dragdrop.js b/railties/html/javascripts/dragdrop.js
index a8ed953a7f..5445d748c3 100644
--- a/railties/html/javascripts/dragdrop.js
+++ b/railties/html/javascripts/dragdrop.js
@@ -10,7 +10,7 @@ var Droppables = {
drops: [],
remove: function(element) {
- this.drops = this.drops.reject(function(e) { return e==element });
+ this.drops = this.drops.reject(function(d) { return d.element==element });
},
add: function(element) {
@@ -93,7 +93,7 @@ var Droppables = {
if (this.isAffected(Event.pointerX(event), Event.pointerY(event), element, this.last_active))
if (this.last_active.onDrop)
- this.last_active.onDrop(element, this.last_active.element);
+ this.last_active.onDrop(element, this.last_active.element, event);
},
reset: function() {
@@ -137,7 +137,11 @@ Draggable.prototype = {
}, arguments[1] || {});
this.element = $(element);
- this.handle = options.handle ? $(options.handle) : this.element;
+ if(options.handle && (typeof options.handle == 'string'))
+ this.handle = Element.Class.childrenWith(this.element, options.handle)[0];
+
+ if(!this.handle) this.handle = $(options.handle);
+ if(!this.handle) this.handle = this.element;
Element.makePositioned(this.element); // fix IE
@@ -147,7 +151,6 @@ Draggable.prototype = {
this.originalTop = this.currentTop();
this.originalX = this.element.offsetLeft;
this.originalY = this.element.offsetTop;
- this.originalZ = parseInt(this.element.style.zIndex || "0");
this.options = options;
@@ -230,7 +233,8 @@ Draggable.prototype = {
this.originalTop = this.currentTop();
}
- this.element.style.zIndex = this.originalZ;
+ if(this.options.zindex)
+ this.element.style.zIndex = this.originalZ;
if(this.options.endeffect)
this.options.endeffect(this.element);
@@ -271,8 +275,14 @@ Draggable.prototype = {
if(!this.dragging) {
var style = this.element.style;
this.dragging = true;
- if(style.position=="") style.position = "relative";
- style.zIndex = this.options.zindex;
+
+ if(Element.getStyle(this.element,'position')=='')
+ style.position = "relative";
+
+ if(this.options.zindex) {
+ this.options.originalZ = parseInt(Element.getStyle(this.element,'z-index') || 0);
+ style.zIndex = this.options.zindex;
+ }
if(this.options.ghosting) {
this._clone = this.element.cloneNode(true);
@@ -344,6 +354,7 @@ var Sortable = {
only: false,
hoverclass: null,
ghosting: false,
+ format: null,
onChange: function() {},
onUpdate: function() {}
}, arguments[1] || {});
@@ -494,11 +505,12 @@ var Sortable = {
var options = Object.extend({
tag: sortableOptions.tag,
only: sortableOptions.only,
- name: element.id
+ name: element.id,
+ format: sortableOptions.format || /^[^_]*_(.*)$/
}, arguments[1] || {});
- return $A(element.childNodes).collect( function(item) {
+ return $(this.findElements(element, options) || []).collect( function(item) {
return (encodeURIComponent(options.name) + "[]=" +
- encodeURIComponent(item.id.split("_")[1]));
+ encodeURIComponent(item.id.match(options.format) ? item.id.match(options.format)[1] : ''));
}).join("&");
}
} \ No newline at end of file
diff --git a/railties/html/javascripts/effects.js b/railties/html/javascripts/effects.js
index d6fbed805e..9e8f8f4965 100644
--- a/railties/html/javascripts/effects.js
+++ b/railties/html/javascripts/effects.js
@@ -120,6 +120,7 @@ Effect.Queue = {
Effect.Base = function() {};
Effect.Base.prototype = {
+ position: null,
setOptions: function(options) {
this.options = Object.extend({
transition: Effect.Transitions.sinoidal,
@@ -169,6 +170,7 @@ Effect.Base.prototype = {
if(this.options.transition) pos = this.options.transition(pos);
pos *= (this.options.to-this.options.from);
pos += this.options.from;
+ this.position = pos;
this.event('beforeUpdate');
if(this.update) this.update(pos);
this.event('afterUpdate');
@@ -207,11 +209,9 @@ Effect.Opacity = Class.create();
Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {
initialize: function(element) {
this.element = $(element);
-
// make this work on IE on elements without 'layout'
if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout))
this.element.style.zoom = 1;
-
var options = Object.extend({
from: Element.getOpacity(this.element) || 0.0,
to: 1.0
@@ -268,69 +268,65 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {
this.start(options);
},
setup: function() {
+ var effect = this;
+
this.restoreAfterFinish = this.options.restoreAfterFinish || false;
this.elementPositioning = Element.getStyle(this.element,'position');
- this.elementStyleTop = this.element.style.top;
- this.elementStyleLeft = this.element.style.left;
- this.elementStyleWidth = this.element.style.width;
- this.elementStyleHeight = this.element.style.height;
- this.elementStyleFontSize = this.element.style.fontSize;
- this.originalTop = this.element.offsetTop;
- this.originalLeft = this.element.offsetLeft;
+
+ effect.originalStyle = {};
+ ['top','left','width','height','fontSize'].each( function(k) {
+ effect.originalStyle[k] = effect.element.style[k];
+ });
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
var fontSize = Element.getStyle(this.element,'font-size') || "100%";
- if(fontSize.indexOf("em")>0) {
- this.fontSize = parseFloat(fontSize);
- this.fontSizeType = "em";
- } else if(fontSize.indexOf("px")>0) {
- this.fontSize = parseFloat(fontSize);
- this.fontSizeType = "px";
- } else if(fontSize.indexOf("%")>0) {
- this.fontSize = parseFloat(fontSize);
- this.fontSizeType = "%";
- }
+ ['em','px','%'].each( function(fontSizeType) {
+ if(fontSize.indexOf(fontSizeType)>0) {
+ effect.fontSize = parseFloat(fontSize);
+ effect.fontSizeType = fontSizeType;
+ }
+ });
+
this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
- if(this.options.scaleMode=='box') {
- this.originalHeight = this.element.clientHeight;
- this.originalWidth = this.element.clientWidth;
- } else if(this.options.scaleMode=='contents') {
- this.originalHeight = this.element.scrollHeight;
- this.originalWidth = this.element.scrollWidth;
- } else {
- this.originalHeight = this.options.scaleMode.originalHeight;
- this.originalWidth = this.options.scaleMode.originalWidth;
- }
+
+ this.dims = null;
+ if(this.options.scaleMode=='box')
+ this.dims = [this.element.clientHeight, this.element.clientWidth];
+ if(this.options.scaleMode=='content')
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ if(!this.dims)
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
},
update: function(position) {
var currentScale = (this.options.scaleFrom/100.0) + (this.factor * position);
if(this.options.scaleContent && this.fontSize)
this.element.style.fontSize = this.fontSize*currentScale + this.fontSizeType;
- this.setDimensions(
- this.originalWidth * currentScale,
- this.originalHeight * currentScale);
+ this.setDimensions(this.dims[0] * currentScale, this.dims[1] * currentScale);
},
finish: function(position) {
if (this.restoreAfterFinish) {
- var els = this.element.style;
- els.top = this.elementStyleTop;
- els.left = this.elementStyleLeft;
- els.width = this.elementStyleWidth;
- els.height = this.elementStyleHeight;
- els.height = this.elementStyleHeight;
- els.fontSize = this.elementStyleFontSize;
+ var effect = this;
+ ['top','left','width','height','fontSize'].each( function(k) {
+ effect.element.style[k] = effect.originalStyle[k];
+ });
}
},
- setDimensions: function(width, height) {
- if(this.options.scaleX) this.element.style.width = width + 'px';
- if(this.options.scaleY) this.element.style.height = height + 'px';
+ setDimensions: function(height, width) {
+ var els = this.element.style;
+ if(this.options.scaleX) els.width = width + 'px';
+ if(this.options.scaleY) els.height = height + 'px';
if(this.options.scaleFromCenter) {
- var topd = (height - this.originalHeight)/2;
- var leftd = (width - this.originalWidth)/2;
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
if(this.elementPositioning == 'absolute') {
- if(this.options.scaleY) this.element.style.top = this.originalTop-topd + "px";
- if(this.options.scaleX) this.element.style.left = this.originalLeft-leftd + "px";
+ if(this.options.scaleY) els.top = this.originalTop-topd + "px";
+ if(this.options.scaleX) els.left = this.originalLeft-leftd + "px";
} else {
- if(this.options.scaleY) this.element.style.top = -topd + "px";
- if(this.options.scaleX) this.element.style.left = -leftd + "px";
+ if(this.options.scaleY) els.top = -topd + "px";
+ if(this.options.scaleX) els.left = -leftd + "px";
}
}
}
@@ -364,10 +360,9 @@ Object.extend(Object.extend(Effect.Highlight.prototype, Effect.Base.prototype),
parseInt(this.options.endcolor.slice(5),16)-this.colors_base[2]];
},
update: function(position) {
- var colors = [
- Math.round(this.colors_base[0]+(this.colors_delta[0]*position)),
- Math.round(this.colors_base[1]+(this.colors_delta[1]*position)),
- Math.round(this.colors_base[2]+(this.colors_delta[2]*position)) ];
+ var effect = this; var colors = $R(0,2).map( function(i){
+ return Math.round(effect.colors_base[i]+(effect.colors_delta[i]*position))
+ });
this.element.style.backgroundColor = "#" +
colors[0].toColorPart() + colors[1].toColorPart() + colors[2].toColorPart();
},
diff --git a/railties/html/javascripts/prototype.js b/railties/html/javascripts/prototype.js
index c0ec65450d..9f5180315d 100644
--- a/railties/html/javascripts/prototype.js
+++ b/railties/html/javascripts/prototype.js
@@ -1,4 +1,4 @@
-/* Prototype JavaScript framework, version 1.4.0_pre7
+/* Prototype JavaScript framework, version 1.4.0_pre11
* (c) 2005 Sam Stephenson <sam@conio.net>
*
* THIS FILE IS AUTOMATICALLY GENERATED. When sending patches, please diff
@@ -11,7 +11,7 @@
/*--------------------------------------------------------------------------*/
var Prototype = {
- Version: '1.4.0_pre7',
+ Version: '1.4.0_pre11',
emptyFunction: function() {},
K: function(x) {return x}
@@ -34,6 +34,17 @@ Object.extend = function(destination, source) {
return destination;
}
+Object.inspect = function(object) {
+ try {
+ if (object == undefined) return 'undefined';
+ if (object == null) return 'null';
+ return object.inspect ? object.inspect() : object.toString();
+ } catch (e) {
+ if (e instanceof RangeError) return '...';
+ throw e;
+ }
+}
+
Function.prototype.bind = function(object) {
var __method = this;
return function() {
@@ -128,34 +139,6 @@ function $() {
return elements;
}
-if (!Array.prototype.push) {
- Array.prototype.push = function() {
- var startLength = this.length;
- for (var i = 0; i < arguments.length; i++)
- this[startLength + i] = arguments[i];
- return this.length;
- }
-}
-
-if (!Function.prototype.apply) {
- // Based on code from http://www.youngpup.net/
- Function.prototype.apply = function(object, parameters) {
- var parameterStrings = new Array();
- if (!object) object = window;
- if (!parameters) parameters = new Array();
-
- for (var i = 0; i < parameters.length; i++)
- parameterStrings[i] = 'parameters[' + i + ']';
-
- object.__apply__ = this;
- var result = eval('object.__apply__(' +
- parameterStrings.join(', ') + ')');
- object.__apply__ = null;
-
- return result;
- }
-}
-
Object.extend(String.prototype, {
stripTags: function() {
return this.replace(/<\/?[^>]+>/gi, '');
@@ -171,27 +154,28 @@ Object.extend(String.prototype, {
unescapeHTML: function() {
var div = document.createElement('div');
div.innerHTML = this.stripTags();
- return div.childNodes[0].nodeValue;
+ return div.childNodes[0] ? div.childNodes[0].nodeValue : '';
},
- parseQuery: function() {
- var str = this;
- if (str.substring(0,1) == '?') {
- str = this.substring(1);
- }
- var result = {};
- var pairs = str.split('&');
- for (var i = 0; i < pairs.length; i++) {
- var pair = pairs[i].split('=');
- result[pair[0]] = pair[1];
- }
- return result;
+ toQueryParams: function() {
+ var pairs = this.match(/^\??(.*)$/)[1].split('&');
+ return pairs.inject({}, function(params, pairString) {
+ var pair = pairString.split('=');
+ params[pair[0]] = pair[1];
+ return params;
+ });
+ },
+
+ inspect: function() {
+ return "'" + this.replace('\\', '\\\\').replace("'", '\\\'') + "'";
}
});
+String.prototype.parseQuery = String.prototype.toQueryParams;
-var _break = new Object();
-var _continue = new Object();
+
+var $break = new Object();
+var $continue = new Object();
var Enumerable = {
each: function(iterator) {
@@ -201,11 +185,11 @@ var Enumerable = {
try {
iterator(value, index++);
} catch (e) {
- if (e != _continue) throw e;
+ if (e != $continue) throw e;
}
});
} catch (e) {
- if (e != _break) throw e;
+ if (e != $break) throw e;
}
},
@@ -213,7 +197,7 @@ var Enumerable = {
var result = true;
this.each(function(value, index) {
if (!(result &= (iterator || Prototype.K)(value, index)))
- throw _break;
+ throw $break;
});
return result;
},
@@ -222,7 +206,7 @@ var Enumerable = {
var result = true;
this.each(function(value, index) {
if (result &= (iterator || Prototype.K)(value, index))
- throw _break;
+ throw $break;
});
return result;
},
@@ -240,7 +224,7 @@ var Enumerable = {
this.each(function(value, index) {
if (iterator(value, index)) {
result = value;
- throw _break;
+ throw $break;
}
});
return result;
@@ -270,7 +254,7 @@ var Enumerable = {
this.each(function(value) {
if (value == object) {
found = true;
- throw _break;
+ throw $break;
}
});
return found;
@@ -359,6 +343,10 @@ var Enumerable = {
iterator(value = collections.pluck(index));
return value;
});
+ },
+
+ inspect: function() {
+ return '#<Enumerable:' + this.toArray().inspect() + '>';
}
}
@@ -381,6 +369,8 @@ var $A = Array.from = function(iterable) {
}
}
+Object.extend(Array.prototype, Enumerable);
+
Object.extend(Array.prototype, {
_each: function(iterator) {
for (var i = 0; i < this.length; i++)
@@ -393,10 +383,80 @@ Object.extend(Array.prototype, {
last: function() {
return this[this.length - 1];
+ },
+
+ compact: function() {
+ return this.select(function(value) {
+ return value != undefined || value != null;
+ });
+ },
+
+ flatten: function() {
+ return this.inject([], function(array, value) {
+ return array.concat(value.constructor == Array ?
+ value.flatten() : [value]);
+ });
+ },
+
+ without: function() {
+ var values = $A(arguments);
+ return this.select(function(value) {
+ return !values.include(value);
+ });
+ },
+
+ inspect: function() {
+ return '[' + this.map(Object.inspect).join(', ') + ']';
}
});
-Object.extend(Array.prototype, Enumerable);
+var Hash = {
+ _each: function(iterator) {
+ for (key in this) {
+ var value = this[key];
+ if (typeof value == 'function') continue;
+
+ var pair = [key, value];
+ pair.key = key;
+ pair.value = value;
+ iterator(pair);
+ }
+ },
+
+ keys: function() {
+ return this.pluck('key');
+ },
+
+ values: function() {
+ return this.pluck('value');
+ },
+
+ merge: function(hash) {
+ return $H(hash).inject($H(this), function(mergedHash, pair) {
+ mergedHash[pair.key] = pair.value;
+ return mergedHash;
+ });
+ },
+
+ toQueryString: function() {
+ return this.map(function(pair) {
+ return pair.map(encodeURIComponent).join('=');
+ }).join('&');
+ },
+
+ inspect: function() {
+ return '#<Hash:{' + this.map(function(pair) {
+ return pair.map(Object.inspect).join(': ');
+ }).join(', ') + '}>';
+ }
+}
+
+function $H(object) {
+ var hash = Object.extend({}, object || {});
+ Object.extend(hash, Enumerable);
+ Object.extend(hash, Hash);
+ return hash;
+}
var Range = Class.create();
Object.extend(Range.prototype, Enumerable);
@@ -435,9 +495,51 @@ var Ajax = {
function() {return new ActiveXObject('Microsoft.XMLHTTP')},
function() {return new XMLHttpRequest()}
) || false;
- }
+ },
+
+ activeRequestCount: 0
}
+Ajax.Responders = {
+ responders: [],
+
+ _each: function(iterator) {
+ this.responders._each(iterator);
+ },
+
+ register: function(responderToAdd) {
+ if (!this.include(responderToAdd))
+ this.responders.push(responderToAdd);
+ },
+
+ unregister: function(responderToRemove) {
+ this.responders = this.responders.without(responderToRemove);
+ },
+
+ dispatch: function(callback, request, transport, json) {
+ this.each(function(responder) {
+ if (responder[callback] && typeof responder[callback] == 'function') {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) {
+ }
+ }
+ });
+ }
+};
+
+Object.extend(Ajax.Responders, Enumerable);
+
+Ajax.Responders.register({
+ onCreate: function() {
+ Ajax.activeRequestCount++;
+ },
+
+ onComplete: function() {
+ Ajax.activeRequestCount--;
+ }
+});
+
Ajax.Base = function() {};
Ajax.Base.prototype = {
setOptions: function(options) {
@@ -476,10 +578,13 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
if (parameters.length > 0) parameters += '&_=';
try {
- if (this.options.method == 'get')
- url += '?' + parameters;
-
- this.transport.open(this.options.method, url,
+ this.url = url;
+ if (this.options.method == 'get')
+ this.url += '?' + parameters;
+
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+ this.transport.open(this.options.method, this.url,
this.options.asynchronous);
if (this.options.asynchronous) {
@@ -545,6 +650,7 @@ Ajax.Request.prototype = Object.extend(new Ajax.Base(), {
|| Prototype.emptyFunction)(transport, json);
(this.options['on' + event] || Prototype.emptyFunction)(transport, json);
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
/* Avoid memory leak in MSIE: clean up the oncomplete event handler */
if (event == 'Complete')
@@ -649,22 +755,13 @@ Ajax.PeriodicalUpdater.prototype = Object.extend(new Ajax.Base(), {
}
});
-document.getElementsByClassName = function(className) {
- var children = document.getElementsByTagName('*') || document.all;
- var elements = new Array();
-
- for (var i = 0; i < children.length; i++) {
- var child = children[i];
- var classNames = child.className.split(' ');
- for (var j = 0; j < classNames.length; j++) {
- if (classNames[j] == className) {
- elements.push(child);
- break;
- }
- }
- }
-
- return elements;
+document.getElementsByClassName = function(className, parentElement) {
+ var children = (document.body || $(parentElement)).getElementsByTagName('*');
+ return $A(children).inject([], function(elements, child) {
+ if (Element.hasClassName(child, className))
+ elements.push(child);
+ return elements;
+ });
}
/*--------------------------------------------------------------------------*/
@@ -674,11 +771,14 @@ if (!window.Element) {
}
Object.extend(Element, {
+ visible: function(element) {
+ return $(element).style.display != 'none';
+ },
+
toggle: function() {
for (var i = 0; i < arguments.length; i++) {
var element = $(arguments[i]);
- element.style.display =
- (element.style.display == 'none' ? '' : 'none');
+ Element[Element.visible(element) ? 'show' : 'hide'](element);
}
},
@@ -688,7 +788,7 @@ Object.extend(Element, {
element.style.display = 'none';
}
},
-
+
show: function() {
for (var i = 0; i < arguments.length; i++) {
var element = $(arguments[i]);
@@ -700,54 +800,50 @@ Object.extend(Element, {
element = $(element);
element.parentNode.removeChild(element);
},
-
+
getHeight: function(element) {
element = $(element);
return element.offsetHeight;
},
+
+ classNames: function(element) {
+ return new Element.ClassNames(element);
+ },
hasClassName: function(element, className) {
- element = $(element);
- if (!element)
- return;
- var a = element.className.split(' ');
- for (var i = 0; i < a.length; i++) {
- if (a[i] == className)
- return true;
- }
- return false;
+ if (!(element = $(element))) return;
+ return Element.classNames(element).include(className);
},
addClassName: function(element, className) {
- element = $(element);
- Element.removeClassName(element, className);
- element.className += ' ' + className;
+ if (!(element = $(element))) return;
+ return Element.classNames(element).add(className);
},
removeClassName: function(element, className) {
- element = $(element);
- if (!element)
- return;
- var newClassName = '';
- var a = element.className.split(' ');
- for (var i = 0; i < a.length; i++) {
- if (a[i] != className) {
- if (i > 0)
- newClassName += ' ';
- newClassName += a[i];
- }
- }
- element.className = newClassName;
+ if (!(element = $(element))) return;
+ return Element.classNames(element).remove(className);
},
// removes whitespace-only text node children
cleanWhitespace: function(element) {
- var element = $(element);
+ element = $(element);
for (var i = 0; i < element.childNodes.length; i++) {
var node = element.childNodes[i];
if (node.nodeType == 3 && !/\S/.test(node.nodeValue))
Element.remove(node);
}
+ },
+
+ empty: function(element) {
+ return $(element).innerHTML.match(/^\s*$/);
+ },
+
+ scrollTo: function(element) {
+ element = $(element);
+ var x = element.x ? element.x : element.offsetLeft,
+ y = element.y ? element.y : element.offsetTop;
+ window.scrollTo(x, y);
}
});
@@ -840,6 +936,43 @@ Insertion.After.prototype = Object.extend(new Abstract.Insertion('afterEnd'), {
}
});
+/*--------------------------------------------------------------------------*/
+
+Element.ClassNames = Class.create();
+Element.ClassNames.prototype = {
+ initialize: function(element) {
+ this.element = $(element);
+ },
+
+ _each: function(iterator) {
+ this.element.className.split(/\s+/).select(function(name) {
+ return name.length > 0;
+ })._each(iterator);
+ },
+
+ set: function(className) {
+ this.element.className = className;
+ },
+
+ add: function(classNameToAdd) {
+ if (this.include(classNameToAdd)) return;
+ this.set(this.toArray().concat(classNameToAdd).join(' '));
+ },
+
+ remove: function(classNameToRemove) {
+ if (!this.include(classNameToRemove)) return;
+ this.set(this.select(function(className) {
+ return className != classNameToRemove;
+ }));
+ },
+
+ toString: function() {
+ return this.toArray().join(' ');
+ }
+}
+
+Object.extend(Element.ClassNames.prototype, Enumerable);
+
var Field = {
clear: function() {
for (var i = 0; i < arguments.length; i++)
diff --git a/railties/html/javascripts/util.js b/railties/html/javascripts/util.js
index c83101b7d2..279bd469a6 100644
--- a/railties/html/javascripts/util.js
+++ b/railties/html/javascripts/util.js
@@ -2,7 +2,8 @@
//
// See scriptaculous.js for full license.
-Object.inspect = function(obj) {
+
+Object.debug = function(obj) {
var info = [];
if(typeof obj in ["string","number"]) {
@@ -20,32 +21,6 @@ Object.inspect = function(obj) {
": {" + info.join(", ") + "}");
}
-// borrowed from http://www.schuerig.de/michael/javascript/stdext.js
-// Copyright (c) 2005, Michael Schuerig, michael@schuerig.de
-
-Array.flatten = function(array, excludeUndefined) {
- if (excludeUndefined === undefined) {
- excludeUndefined = false;
- }
- var result = [];
- var len = array.length;
- for (var i = 0; i < len; i++) {
- var el = array[i];
- if (el instanceof Array) {
- var flat = el.flatten(excludeUndefined);
- result = result.concat(flat);
- } else if (!excludeUndefined || el != undefined) {
- result.push(el);
- }
- }
- return result;
-};
-
-if (!Array.prototype.flatten) {
- Array.prototype.flatten = function(excludeUndefined) {
- return Array.flatten(this, excludeUndefined);
- }
-}
String.prototype.toArray = function() {
var results = [];
@@ -57,28 +32,70 @@ String.prototype.toArray = function() {
/*--------------------------------------------------------------------------*/
var Builder = {
+ NODEMAP: {
+ AREA: 'map',
+ CAPTION: 'table',
+ COL: 'table',
+ COLGROUP: 'table',
+ LEGEND: 'fieldset',
+ OPTGROUP: 'select',
+ OPTION: 'select',
+ PARAM: 'object',
+ TBODY: 'table',
+ TD: 'table',
+ TFOOT: 'table',
+ TH: 'table',
+ THEAD: 'table',
+ TR: 'table'
+ },
+ // note: For Firefox < 1.5, OPTION and OPTGROUP tags are currently broken,
+ // due to a Firefox bug
node: function(elementName) {
- var element = document.createElement('div');
- element.innerHTML =
- "<" + elementName + "></" + elementName + ">";
+ elementName = elementName.toUpperCase();
+
+ // try innerHTML approach
+ var parentTag = this.NODEMAP[elementName] || 'div';
+ var parentElement = document.createElement(parentTag);
+ parentElement.innerHTML = "<" + elementName + "></" + elementName + ">";
+ var element = parentElement.firstChild || null;
+
+ // see if browser added wrapping tags
+ if(element && (element.tagName != elementName))
+ element = element.getElementsByTagName(elementName)[0];
+
+ // fallback to createElement approach
+ if(!element) element = document.createElement(elementName);
+
+ // abort if nothing could be created
+ if(!element) return;
// attributes (or text)
if(arguments[1])
if(this._isStringOrNumber(arguments[1]) ||
(arguments[1] instanceof Array)) {
- this._children(element.firstChild, arguments[1]);
+ this._children(element, arguments[1]);
} else {
var attrs = this._attributes(arguments[1]);
- if(attrs.length)
- element.innerHTML = "<" +elementName + " " +
+ if(attrs.length) {
+ parentElement.innerHTML = "<" +elementName + " " +
attrs + "></" + elementName + ">";
+ element = parentElement.firstChild || null;
+ // workaround firefox 1.0.X bug
+ if(!element) {
+ element = document.createElement(elementName);
+ for(attr in arguments[1])
+ element[attr == 'class' ? 'className' : attr] = arguments[1][attr];
+ }
+ if(element.tagName != elementName)
+ element = parentElement.getElementsByTagName(elementName)[0];
+ }
}
// text, or array of children
if(arguments[2])
- this._children(element.firstChild, arguments[2]);
+ this._children(element, arguments[2]);
- return element.firstChild;
+ return element;
},
_text: function(text) {
return document.createTextNode(text);
@@ -229,7 +246,12 @@ Element.setContentZoom = function(element, percent) {
}
Element.getOpacity = function(element){
- return parseFloat(Element.getStyle(element, "opacity") || '1');
+ var opacity;
+ if (opacity = Element.getStyle(element, "opacity"))
+ return parseFloat(opacity);
+ if (opacity = (Element.getStyle(element, "filter") || '').match(/alpha\(opacity=(.*)\)/))
+ if(opacity[1]) return parseFloat(opacity[1]) / 100;
+ return 1.0;
}
Element.setOpacity = function(element, value){
@@ -237,11 +259,14 @@ Element.setOpacity = function(element, value){
var els = element.style;
if (value == 1){
els.opacity = '0.999999';
- els.filter = null;
+ if(/MSIE/.test(navigator.userAgent))
+ els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'');
} else {
if(value < 0.00001) value = 0;
els.opacity = value;
- els.filter = "alpha(opacity:"+value*100+")";
+ if(/MSIE/.test(navigator.userAgent))
+ els.filter = Element.getStyle(element,'filter').replace(/alpha\([^\)]*\)/gi,'') +
+ "alpha(opacity="+value*100+")";
}
}
@@ -261,22 +286,24 @@ Element.setInlineOpacity = function(element, value){
Element.getDimensions = function(element){
element = $(element);
- // All *Width and *Height properties give 0 on elements with display "none", so enable the element temporarily
- if (element.style.display == "none"){
- var originalVisibility = element.style.visibility;
- var originalPosition = element.style.position;
- element.style.visibility = "hidden";
- element.style.position = "absolute";
- element.style.display = "";
+ // All *Width and *Height properties give 0 on elements with display "none",
+ // so enable the element temporarily
+ if (Element.getStyle(element,'display') == "none"){
+ var els = element.style;
+ var originalVisibility = els.visibility;
+ var originalPosition = els.position;
+ els.visibility = "hidden";
+ els.position = "absolute";
+ els.display = "";
var originalWidth = element.clientWidth;
var originalHeight = element.clientHeight;
- element.style.display = "none";
- element.style.position = originalPosition;
- element.style.visibility = originalVisibility;
+ els.display = "none";
+ els.position = originalPosition;
+ els.visibility = originalVisibility;
return {width: originalWidth, height: originalHeight};
- } else {
- return {width: element.offsetWidth, height: element.offsetHeight};
}
+
+ return {width: element.offsetWidth, height: element.offsetHeight};
}
/*--------------------------------------------------------------------------*/
@@ -445,18 +472,18 @@ Element.Class = {
// gets space-delimited classnames of an element as an array
get: function(element) {
- element = $(element);
- return element.className.split(' ');
+ return $(element).className.split(' ');
},
// functions adapted from original functions by Gavin Kistner
remove: function(element) {
element = $(element);
- var regEx;
- for(var i = 1; i < arguments.length; i++) {
- regEx = new RegExp("(^|\\s)" + arguments[i] + "(\\s|$)", 'g');
- element.className = element.className.replace(regEx, '')
- }
+ var removeClasses = arguments;
+ $R(1,arguments.length-1).each( function(index) {
+ element.className =
+ element.className.split(' ').reject(
+ function(klass) { return (klass == removeClasses[index]) } ).join(' ');
+ });
},
add: function(element) {
diff --git a/railties/lib/rails_generator/generators/applications/app/app_generator.rb b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
index 5dfc79860f..87fe7973ee 100644
--- a/railties/lib/rails_generator/generators/applications/app/app_generator.rb
+++ b/railties/lib/rails_generator/generators/applications/app/app_generator.rb
@@ -62,10 +62,13 @@ class AppGenerator < Rails::Generator::Base
m.template "html/robots.txt", "public/robots.txt"
# Javascripts
- m.file "html/javascripts/prototype.js", "public/javascripts/prototype.js"
- m.file "html/javascripts/effects.js", "public/javascripts/effects.js"
- m.file "html/javascripts/dragdrop.js", "public/javascripts/dragdrop.js"
- m.file "html/javascripts/controls.js", "public/javascripts/controls.js"
+ m.file "html/javascripts/prototype.js", "public/javascripts/prototype.js"
+ m.file "html/javascripts/scriptaculous.js", "public/javascripts/scriptaculous.js"
+ m.file "html/javascripts/util.js", "public/javascripts/util.js"
+ m.file "html/javascripts/effects.js", "public/javascripts/effects.js"
+ m.file "html/javascripts/dragdrop.js", "public/javascripts/dragdrop.js"
+ m.file "html/javascripts/controls.js", "public/javascripts/controls.js"
+ m.file "html/javascripts/slider.js", "public/javascripts/slider.js"
# Docs
m.file "doc/README_FOR_APP", "doc/README_FOR_APP"