I''m trying to extended Ajax.Autocompleter to simplify the process of looking up belongs_to associations, and giving you the option of creating a new target object when the search yields no results. All of which is working fine so far. When the search yeilds no results, a single <li> is pops up where the search results would be and says "not found. click here to create". Clicking hides the current form, and pulls up a create_object form for the target object via an Ajax.Update. All working like it should. The problem comes here: when the new target object is created, I want to server to feed back the id and name of that object into my Autocompleter object, either via an rjs or the ":success" option of the remote form on the creation page. But either way I try it, the javascript that gets to the page won''t recognize the variable that represents my Autocomplete object. I don''t want to post too much code here, but the jist of it is, the autocompeter is written to the page (via an extended form_builder) like this: <script type="text/javascript"> //<![CDATA[ var contribution_artist_name_auto_completer = new Lookup.Autocompleter(''contribution_artist_name'', ''contribution_artist_name_auto_complete'', ''/artists/ auto_complete_for_name'', {idField:''contribution_artist_id'', minChars: 4, newObjectUrl:''http://localhost:3002/artists/new'', paramName:''name'', targetObject:''artist''}) //]]> </script> So, I figure I should be able to call that variable ("contribution_artist_name_auto_completer"), and access a function in it to complete the process once the target object (in this case ''artist'') is created. But sending back an rjs file like this, (if params[:lookup_name_id] == "contribution_artist_name") : page.call((params[:lookup_name_id] + "_auto_completer").to_sym, @artist.id, @artist.name) Throws a javascript error: RJS Error: ReferenceError: contribution_artist_name_auto_completer is not defined. So the question, I guess, is: Is there a special scoping issue that I''m not aware of? Or has anyone had experience similiar to this and maybe could help point me in the right direction? I''d really appreciate any help, John Devine --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Hey John, Before diving further into a client-side maintainance, is there any reason why your AC class is Local, instead of being AJAXy (if you used Ajax.Autocompleter as a base, you would, by definition, always get the latest information from the server side)? If we stay client-side (which I''m not too fond of for AC''s), I need to make sure I understand what you''re saying: 1) The page loads 2) At some point in this loading process there''s an inline script that defines your AC variable. 3) The user looks up something (among local client-side data), doesn''t find it, gets a <li> that lets them create it 4) They click, get a form, fill it up, submit it (which is intercepted and then done through AJAX) 5) The server-side returns an RJS-created JS call that attempts to invoke a method on your local AC, as created on step 2. The reference cannot be found. Is this the actual scheme for your problem? -- Christophe Porteneuve aka TDD tdd-x+CfDp/qHev2eFz/2MeuCQ@public.gmane.org --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Christophe -- With a few exceptions, you''ve got the jist of it -- step 5 is exactly right and the root of my problem -- I can''t see the original Autocompleter variable, either in Firebug, or call it through an RJS or an "onSuccess" call of the remote form. Actually my Autocompleter isn''t Local -- it''s extended from Ajax.Autocompleter : var Lookup = {}; Lookup.Autocompleter = Class.create(); Object.extend(Object.extend(Lookup.Autocompleter.prototype, Ajax.Autocompleter.prototype), { initialize: function(element, update, url, options) { this.baseInitialize(element, update, options); this.options.asynchronous = true; this.options.onComplete = this.onComplete.bind(this); this.options.defaultParams = this.options.parameters || null; this.url = url; this.idFieldId = this.getIdFieldId(this.options); this.idField = $(this.idFieldId); .... ..... this.newObjectUrl = this.options.newObjectUrl; this.targetObject = this.options.targetObject || null; this.setCreateNewDiv(options); this.options.afterUpdateElement = this.afterUpdateElement; }, etc. Actually the first step on the page I''d trying to debug now is to load a "show" page of the parent object that doesn''t orginally include the autocompleter, in this case "play.rhtml". That just lists the attributes of a play. To add an author (or composer, or lyricist) to the play, you click to link_to_remote anchor which updates a div with the form for a "contribution", which is a join object linking an artistic_work, an artist, and an artistic_role. That Ajax-loaded form rhtml includes a hidden input field for the artist_id and a "lookup" field for the artist -- too many for a drop down, and I don''t want them to be able to input someone I don''t have an id for since I''m creating a join object that has "artist" as a belongs_to. The Lookup is obviously reaching my page, as all the ajaxy goodness happens and my extensions are being called, etc. By overriding onComplete, I have the page give the option to create a new target object by calling up a remote_form for the target object: onComplete: function(request) { this.update.innerHTML = request.responseText; if(this.update.firstChild && this.update.firstChild.childNodes.length == 1 ){ if(!this.changed && this.hasFocus) { li = document.createElement(''li''); li.innerHTML = "Not found. Click here to create." Element.addClassName(li,"selected") Event.observe(li,"click", this.createNewObject.bindAsEventListener(this)); this.update.firstChild.appendChild(li); if(this.hasFocus) { this.show(); this.active = true; } } this.entryCount = 0; this.stopIndicator(); this.index = 0; } else { this.updateChoices(request.responseText); } }, The form which is called up by this.createNewObject takes all the attributes of the target object (artist) creates and saves a new active record (via Ajax calls) , and returns the id and name so that they can be populated into the original form. That''s where I get stuck. Do variables that are set to the window via "evalScripts" (which is how the "lookup" autocompleter got there in the first place) reside in the same window context as variables included statically on the orginal page, or is there a special way to access them? Still stuck, so any thoughts appreciated. John On Feb 23, 3:16 am, Christophe Porteneuve <t...-x+CfDp/qHev2eFz/2MeuCQ@public.gmane.org> wrote:> Hey John, > > Before diving further into a client-side maintainance, is there any > reason why your AC class is Local, instead of being AJAXy (if you used > Ajax.Autocompleter as a base, you would, by definition, always get the > latest information from the server side)? > > If we stay client-side (which I''m not too fond of for AC''s), I need to > make sure I understand what you''re saying: > > 1) The page loads > 2) At some point in this loading process there''s an inline script that > defines your AC variable. > 3) The user looks up something (among local client-side data), doesn''t > find it, gets a <li> that lets them create it > 4) They click, get a form, fill it up, submit it (which is intercepted > and then done through AJAX) > 5) The server-side returns an RJS-created JS call that attempts to > invoke a method on your local AC, as created on step 2. The > reference cannot be found. > > Is this the actual scheme for your problem? > > -- > Christophe Porteneuve aka TDD > t...-x+CfDp/qHev2eFz/2MeuCQ@public.gmane.org--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
just a quick revision: the rjs file in the original post was an old version -- should read like this: page.call((params[:lookup_name_id] + "_auto_completer.loadNewObject"), @artist.id, @artist.name) But it still yeilds the same error: contribution_artist_name_auto_completer is not defined. --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---
Further googling finally revealed the answer: from http://www.sergiopereira.com/articles/prototype.js.html at the end of the section: Using the Ajax.Updater class: <quote> In case you''ve tried it before, you know it doesn''t work. The reason is that the script block will be evaluated, and evaluating a script like the above will not create a function named sayHi. It will do nothing. To create this function we need to change our script to create the function. See below. <script language="javascript" type="text/javascript"> sayHi = function(){ alert(''Hi''); }; </script> <input type="button" value="Click Me" onclick="sayHi()"/> Note that in the previous example we did not use the var keyword to declare the variable. Doing so would have created a function object that would be local to the script block (at least in IE). Without the var keyword the function object is scoped to the window, which is our intent. </quote> So, by editing my lookup_field helper (which was copied from the ActionView::Helpers::JavascriptMacrosHelpers#auto_complete_field helper) to not include the "var" at the beginning of my declaration, the whole thing now works as expected. def lookup_field(field_id, options = {}) function = "#{field_id}_auto_completer = new Lookup.Autocompleter(" function << "''#{field_id}'', " function << "''" + (options[:update] || "#{field_id}_auto_complete") + "'', " function << "''#{url_for(options[:url])}''" ... ... function << ('', '' + options_for_javascript(js_options) + '')'') javascript_tag(function) end whereas the first line (and the auto_complete_field helper) read: function = "var #{field_id}_auto_completer = new Lookup.Autocompleter(" Is there a good argument for including the "var" in the first place? Would this be something that should be changed in the rails helpers? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Spinoffs" group. To post to this group, send email to rubyonrails-spinoffs-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-spinoffs-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-spinoffs?hl=en -~----------~----~----~----~------~----~------~--~---