From 10cf9ecafc4b1953cf8289e530cab7a0a751b9c4 Mon Sep 17 00:00:00 2001 From: David Heinemeier Hansson Date: Tue, 3 Jan 2006 04:11:51 +0000 Subject: Added assignment of the Autocompleter object created by JavaScriptMacroHelper#auto_complete_field to a local javascript variables [DHH] Added :on option for PrototypeHelper#observe_field that allows you to specify a different callback hook to have the observer trigger on [DHH] git-svn-id: http://svn-commit.rubyonrails.org/rails/trunk@3378 5ecf4fe2-1ee6-0310-87b1-e25e094e27de --- actionpack/CHANGELOG | 4 ++++ .../action_view/helpers/java_script_macros_helper.rb | 8 ++++++-- actionpack/lib/action_view/helpers/javascript_helper.rb | 14 ++++++++++++++ .../lib/action_view/helpers/javascripts/controls.js | 6 ++++++ .../lib/action_view/helpers/javascripts/prototype.js | 17 ++++++++++------- actionpack/lib/action_view/helpers/prototype_helper.rb | 11 +++++++++-- railties/html/javascripts/controls.js | 6 ++++++ railties/html/javascripts/prototype.js | 17 ++++++++++------- 8 files changed, 65 insertions(+), 18 deletions(-) diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG index 37f9965fa8..aacf62f224 100644 --- a/actionpack/CHANGELOG +++ b/actionpack/CHANGELOG @@ -1,5 +1,9 @@ *SVN* +* Added assignment of the Autocompleter object created by JavaScriptMacroHelper#auto_complete_field to a local javascript variables [DHH] + +* Added :on option for PrototypeHelper#observe_field that allows you to specify a different callback hook to have the observer trigger on [DHH] + * Added JavaScriptHelper#button_to_function that works just like JavaScriptHelper#link_to_function but uses a button instead of a href [DHH] * Added that JavaScriptHelper#link_to_function will honor existing :onclick definitions when adding the function call [DHH] diff --git a/actionpack/lib/action_view/helpers/java_script_macros_helper.rb b/actionpack/lib/action_view/helpers/java_script_macros_helper.rb index 47ae26e54e..f8b45a9e42 100644 --- a/actionpack/lib/action_view/helpers/java_script_macros_helper.rb +++ b/actionpack/lib/action_view/helpers/java_script_macros_helper.rb @@ -72,8 +72,12 @@ module ActionView # or nothing if no entries should be displayed for autocompletion. # # You'll probably want to turn the browser's built-in autocompletion off, - # su be sure to include a autocomplete="off" attribute with your text + # so be sure to include a autocomplete="off" attribute with your text # input field. + # + # The autocompleter object is assigned to a Javascript variable named field_id_auto_completer. + # This object is useful if you for example want to trigger the auto-complete suggestions through + # other means than user input (for that specific case, call the activate method on that object). # # Required +options+ are: # :url:: URL to call for autocompletion results @@ -109,7 +113,7 @@ module ActionView # insertion should be extracted. If this is not specified, # the entire element is used. def auto_complete_field(field_id, options = {}) - function = "new Ajax.Autocompleter(" + function = "var #{field_id}_auto_completer = new Ajax.Autocompleter(" function << "'#{field_id}', " function << "'" + (options[:update] || "#{field_id}_auto_complete") + "', " function << "'#{url_for(options[:url])}'" diff --git a/actionpack/lib/action_view/helpers/javascript_helper.rb b/actionpack/lib/action_view/helpers/javascript_helper.rb index d61167b264..15609d5290 100644 --- a/actionpack/lib/action_view/helpers/javascript_helper.rb +++ b/actionpack/lib/action_view/helpers/javascript_helper.rb @@ -57,6 +57,20 @@ module ActionView }) ) end + + # Returns a link that'll trigger a JavaScript +function+ using the + # onclick handler. + # + # Examples: + # button_to_function "Greeting", "alert('Hello world!')" + # button_to_function "Delete", "if confirm('Really?'){ do_delete(); }") + def button_to_function(name, function, html_options = {}) + html_options.symbolize_keys! + tag(:input, html_options.merge({ + :type => "button", :value => name, + :onclick => (html_options[:onclick] ? "#{html_options[:onclick]}; " : "") + "#{function};" + })) + end # Returns a link that'll trigger a JavaScript +function+ using the # onclick handler. diff --git a/actionpack/lib/action_view/helpers/javascripts/controls.js b/actionpack/lib/action_view/helpers/javascripts/controls.js index 3307f2e2fa..86f34a24f7 100644 --- a/actionpack/lib/action_view/helpers/javascripts/controls.js +++ b/actionpack/lib/action_view/helpers/javascripts/controls.js @@ -152,6 +152,12 @@ Autocompleter.Base.prototype = { setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); }, + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + onHover: function(event) { var element = Event.findElement(event, 'LI'); if(this.index != element.autocompleteIndex) diff --git a/actionpack/lib/action_view/helpers/javascripts/prototype.js b/actionpack/lib/action_view/helpers/javascripts/prototype.js index 545f3af040..fdf4ef1bd2 100644 --- a/actionpack/lib/action_view/helpers/javascripts/prototype.js +++ b/actionpack/lib/action_view/helpers/javascripts/prototype.js @@ -1398,15 +1398,16 @@ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { Abstract.EventObserver = function() {} Abstract.EventObserver.prototype = { - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; + initialize: function() { + this.element = $(arguments[0]); + this.callback = arguments[1]; + this.trigger = arguments[2]; this.lastValue = this.getValue(); if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks(); else - this.registerCallback(this.element); + this.registerCallback(this.element, this.trigger); }, onElementEvent: function() { @@ -1420,11 +1421,13 @@ Abstract.EventObserver.prototype = { registerFormCallbacks: function() { var elements = Form.getElements(this.element); for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); + this.registerCallback(elements[i], this.trigger); }, - registerCallback: function(element) { - if (element.type) { + registerCallback: function(element, trigger) { + if (trigger && element.type) { + Event.observe(element, trigger, this.onElementEvent.bind(this)); + } else if (element.type) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': diff --git a/actionpack/lib/action_view/helpers/prototype_helper.rb b/actionpack/lib/action_view/helpers/prototype_helper.rb index a9a68f474b..d35334a98c 100644 --- a/actionpack/lib/action_view/helpers/prototype_helper.rb +++ b/actionpack/lib/action_view/helpers/prototype_helper.rb @@ -337,11 +337,16 @@ module ActionView # parameters for the XMLHttpRequest. This defaults # to 'value', which in the evaluated context # refers to the new field value. + # :on:: Specifies which event handler to observe. By default, + # it's set to "changed" for text fields and areas and + # "click" for radio buttons and checkboxes. With this, + # you can specify it instead to be "blur" or "focus" or + # any other event. # # Additionally, you may specify any of the options documented in # link_to_remote. def observe_field(field_id, options = {}) - if options[:frequency] and options[:frequency] > 0 + if options[:frequency] && options[:frequency] > 0 build_observer('Form.Element.Observer', field_id, options) else build_observer('Form.Element.EventObserver', field_id, options) @@ -567,7 +572,9 @@ module ActionView javascript = "new #{klass}('#{name}', " javascript << "#{options[:frequency]}, " if options[:frequency] javascript << "function(element, value) {" - javascript << "#{callback}})" + javascript << "#{callback}}" + javascript << ", '#{options[:on]}'" if options[:on] + javascript << ")" javascript_tag(javascript) end diff --git a/railties/html/javascripts/controls.js b/railties/html/javascripts/controls.js index 3307f2e2fa..86f34a24f7 100644 --- a/railties/html/javascripts/controls.js +++ b/railties/html/javascripts/controls.js @@ -152,6 +152,12 @@ Autocompleter.Base.prototype = { setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); }, + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + onHover: function(event) { var element = Event.findElement(event, 'LI'); if(this.index != element.autocompleteIndex) diff --git a/railties/html/javascripts/prototype.js b/railties/html/javascripts/prototype.js index 545f3af040..fdf4ef1bd2 100644 --- a/railties/html/javascripts/prototype.js +++ b/railties/html/javascripts/prototype.js @@ -1398,15 +1398,16 @@ Form.Observer.prototype = Object.extend(new Abstract.TimedObserver(), { Abstract.EventObserver = function() {} Abstract.EventObserver.prototype = { - initialize: function(element, callback) { - this.element = $(element); - this.callback = callback; + initialize: function() { + this.element = $(arguments[0]); + this.callback = arguments[1]; + this.trigger = arguments[2]; this.lastValue = this.getValue(); if (this.element.tagName.toLowerCase() == 'form') this.registerFormCallbacks(); else - this.registerCallback(this.element); + this.registerCallback(this.element, this.trigger); }, onElementEvent: function() { @@ -1420,11 +1421,13 @@ Abstract.EventObserver.prototype = { registerFormCallbacks: function() { var elements = Form.getElements(this.element); for (var i = 0; i < elements.length; i++) - this.registerCallback(elements[i]); + this.registerCallback(elements[i], this.trigger); }, - registerCallback: function(element) { - if (element.type) { + registerCallback: function(element, trigger) { + if (trigger && element.type) { + Event.observe(element, trigger, this.onElementEvent.bind(this)); + } else if (element.type) { switch (element.type.toLowerCase()) { case 'checkbox': case 'radio': -- cgit v1.2.3