draft: I am trying to achieve a way to make calls to an AJAXMethod() and return the response without using an onSuccess: callerMethod() logic.
In the following piece of code, var jsonObjects; function AJAXcallerMethod() { var jsonObj = AJAXMethod(); } function AJAXMethod() { new Ajax.Request(url, { method: 'get', onSuccess: function(transport){ jsonObjects = transport.responseText.evalJSON(); } } return jsonObjects; } this will not work as the AJAX calls are asynchronous, that the jsonObjects is returned, probably, even before the call is actually made and the value jsonObjects is updated later! One way to avoid this problem is to have multiple methods, for example function AJAXcallerMethod() { AJAXMethod(); } function AJAXMethod(url) { new Ajax.Request(url, { method: 'get', onSuccess:AJAXprocessMethod, onFailure: function() { alert("could not make the AJAX call"); } } }); } function AJAXprocessMethod(transport) { var jsonObjects = transport.responseText.evalJSON(); // do whatever you want to with the jsonObjects array } However, I cannot have three methods for one AJAX call and also I have one standard method, that I wrote to essentially RE-USE, to automatically update the corresponding table and form fields based on the keys passed form the server-side on the page without a page refresh using prototype. In this method updateFormAndTableWithJSONresponse(...) that I call from the AJAXcallerMethod(), the method is able to successfully update form and tables as per my requirement, however, I want to monitor this method and continue when this method ends, because any of the custom AJAXcallerMethod() that calls this method has logic that needs to be run ONLY after this method is finished, but I am not sure how I achieve this, that is wait until this method is finished and continue with the custom javascript code? I have heard something similar to AJAX responders that can help me here, but again, there will be three methods for each call, instead I want to re-use this method and also continue with my custom javascript code ONLY after the method call ends. How can I use AJAX responder to achieve this? function updateFormAndTableWithJSONresponse(formId, actionName, actionMethod, refTableId, throwErrorIfNotFound) { var contextPath = document.forms[0].contextPath.value; if(contextPath == null || contextPath == '') { alert('could not find the hidden contextPath property in the form'); return false; } var url = contextPath + '/' + actionName + ".do?method=" + actionMethod + "&"; // collect all the field values associated with this form whose id is 'ajaxFormId' // and attach it to do a get(), isn't there a way to attach all form fields in post // automatically like we do in a normal HTTPRequest doPost()? url = url + Form.serialize($(formId)); // I mean we may be imposing a limitation of 3kb in doGet() // Create the XMLHttpRequest object and send it via the Ajax.Request prototype.js method new Ajax.Request(url, { method: 'get', onSuccess: function(transport){ var jsonObjects = transport.responseText.evalJSON(); // If it is not an array (default return tyep), it must be an individual jsonObject // that contains error message if(jsonObjects == null) // also check for type as object { if(throwErrorIfNotFound) alert('could not get a JSON response '); return; } if(jsonObjects.length === undefined) { if(!(jsonObjects['errorMessage'] === undefined)) { var errMsgDiv = $('errMsg'); errMsgDiv.style.display = 'block'; errMsgDiv.innerHTML = jsonObjects['errorMessage']; } } else { var jsonObjIndex = 0; // use reference table to update contentTable only when refTableId is not null if(refTableId != null && refTableId != '') { // tableRowContent is an array where each row represents the table row in the form // of a jsonObjects var tableRowContent = (jsonObjects[0])['tableRowContent']; // If you do not want to send a table, it is fine too if(!(tableRowContent === undefined)) { updateContentTableWithJSONObjContent(tableRowContent, refTableId, 'contentTableId', throwErrorIfNotFound); jsonObjIndex = 1; // because the first jsonObject is a tableRowContent } } // update individual elements in the form using the keys passed // usually you can keep all of the keys of individual objects // put inthe same jsonObject // as in jsonObj.put("shares", "300.234"); // jsonObj.put("trancheVestDate", "10/20/2001"); for(; jsonObjIndex < jsonObjects.length ; jsonObjIndex++) { updateFormWithJSONObjContent(jsonObjects[jsonObjIndex], throwErrorIfNotFound); } } } }); return true; } // does not handle multiple yet!!! function updateFormWithJSONObjContent(jsonObjContent, throwErrorIfNotFound) { for(var nameKey in jsonObjContent) { // search the element whose name attribute value is nameKey // follow the convention with element id = name + 'Id' inputElement = $(nameKey + 'Id'); // handle the case where you cannot find the field in the table row TR // whose name='key' that is being passed from the action class in the // tableRow jsonObject if(inputElement == null || inputElement.length == 0) { if(throwErrorIfNotFound) alert('could not find an element with id=' + nameKey + 'Id' + ' to be updated'); continue; // continue with the next key } // update the value with the correct value to be updated! inputElement.value = jsonObjContent[nameKey]; } return true; } function updateContentTableWithJSONObjContent(tableRowContent, refTableId, contentTableId, throwErrorIfNotFound) { // avoid showing just the header when no rows are passed! if(tableRowContent.size() == 0) { alert('no rows content passed'); return false; } // Maintain many hidden tables with just one header and one dummy row // that has all validations such as onchange="validateDecimal (this)", // style and default attributes set such as disabled="disabled", this will // be the model that will be cloned and added to the contentTable // Access the hidden table, get the first row in tbody // make copies of it with values sent from the tableRowContent array // copy the static header first, convention: the reference table MUST have <tHead .../> defined var hiddenTableTHead = $(refTableId).tHead; // I donot want to work on the original hidden table // i.e., adding new rows would add to the reference of // the original hidden table tBody // Hide the content table as per prototype and then remove visibility $(contentTableId).hide().setStyle({visibility: ''}); // clear the complete contentTable content, due to previous table updates!!! for(var i = $(contentTableId).tBodies[0].rows.length - 1; i >= 0 ; i--) { $(contentTableId).tBodies[0].deleteRow(i); } // handle special scenarios with no table bodies and table header if($(contentTableId).tBodies.length == 0) { if(throwErrorIfNotFound) alert('cannot find the TBODY for the content table with id:' + contentTableId); $(contentTableId).tBodies[0] = document.createElement('TBODY'); } if($(contentTableId).tHead == null) { if(throwErrorIfNotFound) alert('cannot find the THEAD for the content table with id:' + contentTableId); $(contentTableId).tHead = document.createElement('THEAD'); } // get the reference to the contentTable Body var contentTableTBody = $(contentTableId).tBodies[0]; // document.createElement('TBODY'); // hiddenTableTBody.innerHTML = $('table1Id').tBodies[0].innerHTML; // Object.extend(hiddenTableTBody, $('table1Id').tBodies[0]); // Throws an exception that the rows are not copied (is this shallow copy) // and innerHTML would return object using Object.clone() // Object.clone($('table1Id').tBodies[0]); // get a copy of the reference table TBody row which contains everything you want, // textboxes, checkboxes,... with name='shares',... and so on.. // this is unfortunate that we are still sticking to name='' convention in each row // however, this makes sense in our application because we need var hiddenTableDummyTR = document.createElement('TR'); hiddenTableDummyTR = $(refTableId).tBodies[0].rows[0]; // A reference row must always exist!!! if(hiddenTableDummyTR == null) { if(throwErrorIfNotFound) alert('cannot find the reference row in the reference table with id:' + refTableId); return false; } // setting a property that only has a getter error when using Object.extend // Object.extend(hiddenTableDummyTD, $('table1Id').tBodies[0].rows [0]); // remove all rows from the cloned copy of hiddenTableTBody // hiddenTableTBody.innerHTML = ''; // where as this code seems to throw exception // for(var i = 0; i < hiddenTableTBody.rows.length; i++) // { // hiddenTableTBody.deleteRow(); // } // Update the header of the content table with the header of the reference table $('contentTableId').tHead.innerHTML = $(refTableId).tHead.innerHTML; // Update body // now add new rows with new content var tableRowJSONObj; var contentTableTBodyTR; for(var i = 0 ; i < tableRowContent.size(); i++) { tableRowJSONObj = tableRowContent[i]; // an array of JSONObjects would return a JSONObject if(tableRowJSONObj != null) { // create a new row in the hiddenTableTBody contentTableTBody.insertRow(i); // copy the innerHTML to get the elements with default values and styles contentTableTBody.rows[i].innerHTML = hiddenTableDummyTR.innerHTML; // get the reference contentTableTBodyTR to point to the row in the contentTable contentTableTBodyTR = contentTableTBody.rows[i]; // search for the element whose name attribute is equal to // and get only one of them.. currently this does not handle multiple // elements whose name is same in the SAME ROW var inputElement; // the keys in the tableRow JSONObject are 'name' attributes of each // table row that you will be updating for(var nameKey in tableRowJSONObj) { // search the element whose 'name=' attribute value is nameKey inputElement = contentTableTBodyTR.select('[name="' + nameKey + '"]'); // handle the case where you cannot find the field in the table row TR // whose name='key' that is being passed from the action class in the // tableRow jsonObject if(inputElement == null || inputElement.length == 0) { if(throwErrorIfNotFound) alert('cannot find the element with name:' + nameKey + ' in the reference row'); continue; } inputElement[0].value = tableRowJSONObj[nameKey]; } } } // use prototype's custom $('table1Id').show() and $ ('table1Id').hide() methods // however, show() and hide() methods won't work when visibility is set to 'hidden' // then apply the appear effect on the table $('contentTableId').appear({duration: 1.0}); return true; } --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Prototype & script.aculo.us" group. To post to this group, send email to prototype-scriptaculous@googlegroups.com To unsubscribe from this group, send email to prototype-scriptaculous+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/prototype-scriptaculous?hl=en -~----------~----~----~----~------~----~------~--~---