Changeset 859 for trunk


Ignore:
Timestamp:
03/13/11 00:05:16 (8 years ago)
Author:
gav
Message:

Rework entry create and save ajax to allow multiple page element updates with JSON.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/grails-app/controllers/EntryDetailedController.groovy

    r838 r859  
    1010 
    1111    // the delete, save and update actions only accept POST requests 
    12     static allowedMethods = [delete:'POST', save:'POST', update:'POST'] 
     12    static allowedMethods = [delete:'POST', save:'POST', update:'POST', ajaxCreate:'POST', ajaxSave:'POST'] 
    1313 
    1414    def list = { 
     
    106106    def ajaxCreate = { 
    107107        if(!params.taskId || !params.entryTypeId) { 
    108             response.status = 403 
    109108            params.errorMessage = g.message(code: "entry.create.no.params.ajax") 
    110             render(template: "/shared/messages") 
     109            render(contentType:"text/json", status: 403, template: "/shared/messages") 
    111110            return 
    112111        } 
     
    115114 
    116115        if(!taskInstance) { 
    117             response.status = 403 
    118116            params.errorMessage = g.message(code:"default.not.found", args:['Task',params.taskId]) 
    119             render(template: "/shared/messages") 
     117            render(contentType:"text/json", status: 403, template: "/shared/messages") 
    120118            return 
    121119        } 
     
    123121        // Check for Complete task. 
    124122        if(taskInstance.taskStatus.id == 3) { 
    125             response.status = 403 
    126123            params.errorMessage = g.message(code:"task.operationNotPermittedOnCompleteTask") 
    127             render(template: "/shared/messages") 
     124            render(contentType:"text/json", status: 403, template: "/shared/messages") 
    128125            return 
    129126        } 
     
    133130        entryInstance.task = taskInstance 
    134131        entryInstance.entryType = EntryType.read(params.entryTypeId) 
    135         render(template: "create", model: ['entryInstance': entryInstance]) 
    136     } 
     132        def model = ['entryInstance': entryInstance] 
     133 
     134        render(contentType:"text/json") { 
     135            updates = array { 
     136                element([ mode: 'replace', target:"$params.target", content: g.render(template: 'create', model:model) ]) 
     137            } 
     138        } 
     139 
     140    } // ajaxCreate 
    137141 
    138142    def ajaxSave = { 
     
    142146        if(!result.error) { 
    143147            def entryList = Entry.withCriteria { 
    144                                                                 eq("entryType", result.entryInstance.entryType) 
    145                                                                 task { 
    146                                                                     idEq(result.taskId) 
    147                                                                 } 
    148                                                         } 
    149             render(template: "list", model: ['entryList': entryList]) 
    150             return 
    151         } 
    152  
    153         if(result.error.code != "default.create.failure") { 
    154             response.status = 403 
     148                                            eq("entryType", result.entryInstance.entryType) 
     149                                            task { 
     150                                                idEq(result.taskId) 
     151                                            } 
     152                                    } 
     153 
     154            def model = ['entryList': entryList] 
     155 
     156            render(contentType:"text/json") { 
     157                updates = array { 
     158                    element([ mode: 'replace', target:"$params.target", content: g.render(template: 'list', model:model) ]) 
     159                } 
     160            } 
     161            return 
     162        } 
     163 
     164        if(result.error.code != "default.create.failure") 
    155165            params.errorMessage = g.message(code: result.error.code) 
    156             render(template: "/shared/messages") 
    157             return 
    158         } 
    159  
    160         response.status = 403 
    161         render(template: "create", model: ['entryInstance': result.entryInstance]) 
     166 
     167        def model = ['entryInstance': result.entryInstance] 
     168        render(contentType:"text/json", status: 403, template: "create", model: model) 
    162169    } // ajaxSave 
    163170 
  • trunk/grails-app/views/taskDetailed/_showProcedureTab.gsp

    r833 r859  
    4646                            value="Add PM Entry" 
    4747                            onclick="getCreateEntryForm(jQuery('#pmEntryContainer'), 
    48                                                                                 jQuery('#createPMEntryContainer'), 
    4948                                                                                jQuery('#pmEntryButton'), 
    50                                                                                 {taskId: ${taskInstance?.id}, entryTypeId: 6})" /> 
     49                                                                                {target: '#createPMEntryContainer', 
     50                                                                                taskId: ${taskInstance?.id}, 
     51                                                                                entryTypeId: 6})" /> 
    5152            </span> 
    5253        </div> 
  • trunk/grails-app/views/taskDetailed/_showTaskTab.gsp

    r846 r859  
    231231                        value="Add Fault" 
    232232                        onclick="getCreateEntryForm(jQuery('#entryFaultContainer'), 
    233                                                                             jQuery('#createEntryFaultContainer'), 
    234233                                                                            jQuery('#entryFaultButton'), 
    235                                                                             {taskId: ${taskInstance?.id}, entryTypeId: 1})" /> 
     234                                                                            {target: '#createEntryFaultContainer', 
     235                                                                            taskId: ${taskInstance?.id}, 
     236                                                                            entryTypeId: 1})" /> 
    236237        </span> 
    237238    </div> 
     
    260261                        value="Add Cause" 
    261262                        onclick="getCreateEntryForm(jQuery('#entryCauseContainer'), 
    262                                                                             jQuery('#createEntryCauseContainer'), 
    263263                                                                            jQuery('#entryCauseButton'), 
    264                                                                             {taskId: ${taskInstance?.id}, entryTypeId: 2})" /> 
     264                                                                            {target: '#createEntryCauseContainer', 
     265                                                                            taskId: ${taskInstance?.id}, 
     266                                                                            entryTypeId: 2})" /> 
    265267        </span> 
    266268    </div> 
     
    289291                        value="Add Work Done" 
    290292                        onclick="getCreateEntryForm(jQuery('#workDoneContainer'), 
    291                                                                             jQuery('#createWorkDoneContainer'), 
    292293                                                                            jQuery('#workDoneButton'), 
    293                                                                             {taskId: ${taskInstance?.id}, entryTypeId: 3})" /> 
     294                                                                            {target: '#createWorkDoneContainer', 
     295                                                                            taskId: ${taskInstance?.id}, 
     296                                                                            entryTypeId: 3})" /> 
    294297        </span> 
    295298    </div> 
  • trunk/web-app/js/application.js

    r825 r859  
    1919} 
    2020 
    21 function errorIndication() { 
    22     return jQuery('#jQueryAjaxDefaultError').clone(); 
     21function errorIndication(jqXHR, textStatus, errorThrown) { 
     22    return jQuery('#jQueryAjaxDefaultError').clone().append('Status:'+jqXHR.status+', '+textStatus+'.'); 
    2323} 
     24 
     25// Apply updates to multiple page elements. 
     26// @json JSON response object from an ajax request. 
     27// @json.updates Array of element updates to apply. 
     28// @element.mode The update mode: execute or replace, prepend, append. 
     29// @element.script Script to execute, if execute mode. 
     30// @element.target jQuery target selector, if update mode. 
     31// @element.content Content to update target with, if update mode. 
     32function applyElementUpdates(json) { 
     33    var updates; 
     34    var script; 
     35 
     36    if(json.updates) { 
     37        updates = json.updates; 
     38        var element; 
     39        var scripts = new Array(); 
     40 
     41        for(element in updates) { 
     42            element = updates[element]; 
     43 
     44            switch(element.mode) { 
     45                case 'execute': 
     46                    scripts.push(element.script); 
     47                    break; 
     48                case 'replace': 
     49                    jQuery(element.target).html(element.content); 
     50                    break; 
     51                case 'prepend': 
     52                    jQuery(element.target).prepend(element.content); 
     53                    break; 
     54                case 'append': 
     55                    jQuery(element.target).append(element.content); 
     56                    break; 
     57            } 
     58        } 
     59 
     60        // Run scripts. 
     61        for(script in scripts) { 
     62            script = scripts[script]; 
     63            eval(script); 
     64        } 
     65 
     66    } // if(json.updates) 
     67} // applyElementUpdates 
     68 
     69 
     70 
  • trunk/web-app/js/taskShow.js

    r851 r859  
    11 
    2 // Load data into createContainer and register events. 
    3 function loadCreateContainer(data, createContainer, listContainer, button) { 
    4         // Load the response data and show container. 
    5         createContainer.html(data).slideDown(800); 
    6         // Scroll the window. 
    7         jQuery('html,body').animate({scrollTop: createContainer.offset().top - 70}, 900, function() { 
    8             createContainer.find(':input[name="comment"]').focus(); 
    9         }); 
    10         // Register 'submit_*' input button click handlers. 
    11         createContainer.find('input[name^="submit_"]').click(function(){ 
    12             createContainer.find(':input[name="submitAction"]').val(jQuery(this).attr('name')); 
    13             createContainer.find('form:first').submit(); 
    14         }); 
    15         // Hijack form submit to use our function. 
    16         var eventData = {listContainer:listContainer, createContainer:createContainer, button:button}; 
    17         createContainer.find('form:first').submit(eventData, submitCreateEntryForm); 
    18         // Register the close img click handler. 
    19         createContainer.find('.pane_close img').click(function(){ 
    20             createContainer.slideUp(600); 
    21             button.show(600, function() { 
    22                 if(jQuery.browser.msie) { 
    23                     jQuery(this).get(0).style.removeAttribute('filter'); // Remove blur/fuzzy text in IE. 
    24                 } 
    25             }); 
    26         }); 
     2function showButton(button) { 
     3    button.show(600, function() { 
     4        if(jQuery.browser.msie) { 
     5            jQuery(this).get(0).style.removeAttribute('filter'); // Remove blur/fuzzy text in IE. 
     6        } 
     7    }); 
     8} 
     9 
     10function createEntryFormInit(target, listContainer, button) { 
     11 
     12    // Show. 
     13    target.slideDown(800); 
     14    // Scroll the window. 
     15    jQuery('html,body').animate({scrollTop: target.offset().top - 70}, 900, function() { 
     16        target.find(':input[name="comment"]').focus(); 
     17    }); 
     18    // Register 'submit_*' input button click handlers. 
     19    target.find('input[name^="submit_"]').click(function(){ 
     20        target.find(':input[name="submitAction"]').val(jQuery(this).attr('name')); 
     21        target.find('form:first').submit(); 
     22    }); 
     23    // Redirect form submit to use our function. 
     24    var eventData = {listContainer:listContainer, source:target, button:button}; 
     25    target.find('form:first').submit(eventData, submitCreateEntryForm); 
     26    // Register the close img click handler. 
     27    target.find('.pane_close img').click(function(){ 
     28        target.slideUp(600); 
     29        showButton(button); 
     30    }); 
     31 
    2732} 
    2833 
     
    3439    event.preventDefault(); 
    3540    var listContainer = event.data.listContainer; 
    36     var createContainer = event.data.createContainer; 
     41    var source = event.data.source; 
    3742    var button = event.data.button; 
    38     var form = createContainer.find('form:first'); 
     43    var form = source.find('form:first'); 
    3944 
    4045    // On success reload listContainer. 
    41     function success(data, textStatus, jqXHR){ 
    42         createContainer.hide(); 
    43         listContainer.html(data); 
    44         button.show(600, function() { 
    45             if(jQuery.browser.msie) { 
    46                 jQuery(this).get(0).style.removeAttribute('filter'); // Remove blur/fuzzy text in IE. 
    47             } 
    48         }); 
     46    function success(data, textStatus, jqXHR) { 
     47        source.hide(); 
     48        applyElementUpdates(data); 
     49        showButton(button); 
    4950    } 
    5051 
    5152    // On create failure controller sets 403 and returns the form template. 
    52     function error(jqXHR, textStatus, errorThrown){ 
    53         if(jqXHR.status == 403 && jqXHR.responseText){ 
    54             loadCreateContainer(jqXHR.responseText, createContainer, listContainer, button); 
     53    function error(jqXHR, textStatus, errorThrown) { 
     54        if(jqXHR.status == 403 && jqXHR.responseText) { 
     55            source.html(jqXHR.responseText); 
     56            createEntryFormInit(source, listContainer, button); 
    5557        } 
    5658        else { 
    57             createContainer.html(savedHtml); 
    58             createContainer.prepend(errorIndication().show()).slideDown(600); 
     59            source.html(savedHtml); 
     60            source.prepend(errorIndication(jqXHR, textStatus, errorThrown).show()).slideDown(600); 
    5961            // Scroll the window. 
    60             jQuery('html,body').animate({scrollTop: createContainer.offset().top - 70}, 900, function() { 
    61                 createContainer.find(':input[name="comment"]').focus(); 
     62            jQuery('html,body').animate({scrollTop: source.offset().top - 70}, 900, function() { 
     63                source.find(':input[name="comment"]').focus(); 
    6264            }); 
    6365        } 
     
    6567 
    6668    // Start. 
    67     var savedHtml = createContainer.children().detach(); 
    68     createContainer.html(loadingIndication().show()).slideDown(600); 
     69    var savedHtml = source.children().detach(); 
     70    var params = form.serializeArray(); 
     71    params.push({name:'target', value:listContainer.selector}); 
     72    source.html(loadingIndication().show()).slideDown(600); 
    6973 
    7074    jQuery.ajax({ 
    7175        url: actionUrl, 
    72         data: form.serializeArray(), 
     76        data: params, 
     77        type: 'POST', 
     78        dataType: 'json', 
    7379        success: success, 
    7480        error: error 
     
    7884// Get a create Entry form via AJAX. 
    7985// @listContainer Container object to reload list into. 
    80 // @createContainer Container object to load response into. 
    8186// @button Button object used to trigger this function. 
    8287// @params Params map to pass to actionUrl. 
    83 function getCreateEntryForm(listContainer, createContainer, button, params) { 
     88// @params.target Selector indicating target to load response into. 
     89function getCreateEntryForm(listContainer, button, params) { 
    8490 
    8591    var actionUrl = getContextPath()+"/entryDetailed/ajaxCreate/"; 
     92    var target = jQuery(params.target); 
    8693 
    87     // On success load createContainer. 
    88     function success(data, textStatus, jqXHR){ 
    89         loadCreateContainer(data, createContainer, listContainer, button); 
     94    // On success load target. 
     95    function success(data, textStatus, jqXHR) { 
     96        applyElementUpdates(data); 
     97        createEntryFormInit(target, listContainer, button); 
    9098    } 
    9199 
    92100    // On error show controller responseText or show default error. 
    93     function error(jqXHR, textStatus, errorThrown){ 
    94         if(jqXHR.status == 403 && jqXHR.responseText){ 
    95             loadCreateContainer(jqXHR.responseText, createContainer, listContainer, button); 
     101    function error(jqXHR, textStatus, errorThrown) { 
     102        if(jqXHR.status == 403 && jqXHR.responseText) { 
     103            target.html(jqXHR.responseText); 
    96104        } 
    97105        else { 
    98             createContainer.html(errorIndication().show()).slideDown(600); 
     106            target.html(errorIndication(jqXHR, textStatus, errorThrown).show()); 
    99107        } 
    100         button.show(600, function() { 
    101             if(jQuery.browser.msie) { 
    102                 jQuery(this).get(0).style.removeAttribute('filter'); // Remove blur/fuzzy text in IE. 
    103             } 
    104         }); 
     108        showButton(button); 
    105109    } 
    106110 
    107111    // Start. 
    108112    button.hide(600); 
    109     createContainer.html(loadingIndication().show()).slideDown(600); 
     113    target.html(loadingIndication().show()).slideDown(600); 
    110114 
    111115    jQuery.ajax({ 
    112116        url: actionUrl, 
    113117        data: params, 
     118        type: 'POST', 
     119        dataType: 'json', 
    114120        success: success, 
    115121        error: error 
Note: See TracChangeset for help on using the changeset viewer.