Changeset 77 for unicoders

Show
Ignore:
Timestamp:
06/30/07 19:36:35 (19 months ago)
Author:
steadicat
Message:

Added support for boolean fields.
Various fixes and refactoring.

Location:
unicoders/trunk/unicoders
Files:
5 modified

Legend:

Unmodified
Added
Removed
  • unicoders/trunk/unicoders/adminedit/media/scripts/adminedit.js

    r76 r77  
     1var ADMIN_URL = '/admin/'; 
     2var ADMINEDIT_URL = '/adminedit/'; 
     3var THROBBER ='<img src="/media/images/throbber.gif" class="throbber"/>'; 
     4var MESSAGE = '<ul class="messagelist"><li>Click any field to edit it in place</li></ul>'; 
     5 
     6function stopPropagation(event) { event.stopPropagation(); } 
     7 
    18function getFieldId(cell) { 
    29    var cell = $(cell); 
     
    1926} 
    2027 
    21 function getTypeName() { 
    22     return document.location.href.split('/').slice(-2, -1)[0]; 
    23 } 
    24 function getObjectId(cell) { 
    25     var id = $(cell).parent().find('a').attr('href'); 
    26     return id.substring(0, id.length-1); 
    27 } 
    28  
    2928function getUrl(cell) { 
    30     // build the url 
    31     var type = getTypeName(); 
    32     var id = getObjectId(cell); 
    33     var field = getFieldId(cell); 
    34     return '/adminedit/edit/'+type+'/'+id+'/'+field; 
     29    return $(cell).parent().find('a').attr('href') + getFieldId(cell); 
    3530} 
    3631 
     
    3833    return $(cell).parent().find('th input')[0].checked; 
    3934} 
    40 function editField() { 
     35 
     36function focusForm(cell) { 
     37    var form = $(cell).find('input, textarea, select'); 
     38    if (form.length > 0) form[0].focus(); 
     39} 
     40 
     41 
     42function edit() { 
     43    var cell = this; 
     44    var bool = null; 
     45 
     46    function editOne(c, b) { 
     47        if (b != null) { 
     48            editBooleanField(c, !b); 
     49        } else { 
     50            editField(c); 
     51        } 
     52    } 
     53 
     54    // special case for bool fields 
     55    if ($(cell).find('img').length > 0) bool = ($(cell).find('img').attr('alt') == 'True'); 
     56 
    4157    // if the row we are editing is selected 
    42     if (isRowSelected(this)) { 
     58    if (isRowSelected(cell)) { 
    4359        // do the same edit on all the other rows that are selected 
    44         getCellsInColumn(this).each(function() { 
    45             if (isRowSelected(this)) editSingleField.call(this, false); 
     60        getCellsInColumn(cell).each(function() { 
     61            if (isRowSelected(this)) editOne(this, bool); 
    4662        }); 
    4763    } else { 
    48         editSingleField.call(this, true); 
    49     } 
    50 } 
    51  
    52 function setupForm(target, single) { 
    53     var form = $(target).find('input, textarea, select'); 
     64        editOne(cell, bool); 
     65        focusForm(cell); 
     66    } 
     67} 
     68 
     69function save() { 
     70    var form = this; 
     71    var cell = $(form).parent(); 
     72    // if the row we are editing is selected 
     73    if (isRowSelected(cell)) { 
     74        // save all the other rows that are selected 
     75        getCellsInColumn(cell).each(function() { 
     76            if (isRowSelected(this)) saveField($(this).find('input, textarea, select')); 
     77        }); 
     78    } else { 
     79        saveField(form); 
     80        focusForm(cell); 
     81    } 
     82} 
     83 
     84function editBooleanField(cell, value) { 
     85    var args = {}; 
     86    args['toggle'] = value; 
     87 
     88    // throbber 
     89    $(cell).append(THROBBER); 
     90 
     91    $.post(getUrl(cell), args, function(data) { 
     92        var img = $($(cell).find('img')[0]); 
     93 
     94        data = data.split('\n')[0]; 
     95 
     96        if ((data == 'True') || (data == 'False')) { 
     97            img.attr('alt', data); 
     98            // remove the throbber 
     99            $(cell).find('img.throbber').remove(); 
     100        } 
     101 
     102        if (data == 'True') { 
     103            img.attr('src', img.attr('src').replace('-no', '-yes')); 
     104        } else if (data == 'False') { 
     105            img.attr('src', img.attr('src').replace('-yes', '-no')); 
     106        } 
     107    }); 
     108} 
     109 
     110function editField(cell) { 
     111    // throbber 
     112    $(cell).append(THROBBER); 
     113 
     114    // ajax request for the form widget 
     115    $.get(getUrl(cell), function(data) { 
     116        // insert the ajax response in the page 
     117        $(cell).html(data); 
     118        setupForm(cell); 
     119    }); 
     120} 
     121 
     122function saveField(form) { 
     123    var cell = $(form).parent(); 
     124 
     125    // throbber 
     126    cell.append(THROBBER); 
     127 
     128    // just one argument to the post: the field we are editing with its new value 
     129    var args = {}; 
     130    if ($(form).attr('value')) { 
     131        args[$(form).attr('name')] = $(form).attr('value'); 
     132    } else { 
     133        args[$(form).attr('name')] = ''; 
     134    } 
     135 
     136    // ajax post to edit the object 
     137    $.post(getUrl(cell), args, function(data) { 
     138        // display the new value in the page 
     139        $(cell).html(data); 
     140 
     141        // in case of validation error 
     142        setupForm(cell); 
     143    }); 
     144} 
     145 
     146function setupForm(cell) { 
     147    var form = $(cell).find('input, textarea, select'); 
    54148    if (form.length == 0) return; 
    55149 
    56150    // do not start the edit again if we click on a form element 
    57     form.click(function(event) { event.stopPropagation(); event.preventDefault(); }); 
     151    form.click(stopPropagation); 
    58152    // on blur: save 
    59     form.blur(function() { saveField.call(this, single); }); 
     153    form.blur(save); 
    60154    // on enter: save 
    61155    form.keypress(function(event) { 
    62         if (event.keyCode == 13) saveField.call(this, single); 
    63     }); 
    64  
    65  
     156        if (event.keyCode == 13) save.call(this); 
     157    }); 
     158 
     159    // edit all selected fields simultaneously 
    66160    function changeField() { 
    67161        function innerChangeField() { 
    68             var cell = $(target); 
    69             if (target.tagName == 'A') cell = $(target).parent(); 
    70162            getCellsInColumn(cell).each(function() { 
    71163                if (isRowSelected(this)) { 
     
    75167            }); 
    76168        }; 
    77         setTimeout(innerChangeField, 10); 
     169        // let the current element edit before updating the other ones 
     170        setTimeout(innerChangeField, 1); 
    78171    } 
    79172    form.change(changeField); 
    80173    form.keypress(changeField); 
    81  
    82     // focus on the new form widget 
    83     if (single) form[0].focus(); 
    84 } 
    85  
    86 function editSingleField(single) { 
    87     var target = this; 
    88     // keep the link if present 
    89     if ($(target).find('a').length > 0) { 
    90         target = $(this).find('a')[0]; 
    91     } 
    92  
    93     // throbber 
    94     $(target).append('<img src="/media/images/throbber.gif"/>'); 
    95  
    96     // ajax request for the form widget 
    97     $.get(getUrl(this), function(data) { 
    98         // insert the ajax response in the page 
    99         $(target).html(data); 
    100  
    101         setupForm(target, single); 
    102     }); 
    103 } 
    104  
    105 function saveField(single) { 
    106     var cell = $(this).parent(); 
    107 //    var target = cell; 
    108 //    if (cell[0].tagName == 'SPAN') cell = cell.parent(); 
    109  
    110     if (!single) { 
    111         var column = getCellsInColumn(cell); 
    112         var form = this; 
    113         column.each(function() { 
    114             if (isRowSelected(this)) saveField.call($(this).find('input, textarea, select'), true); 
    115         }); 
    116     } else { 
    117  
    118         // throbber 
    119         cell.append('<img src="/media/images/throbber.gif"/>'); 
    120  
    121         // just one argument to the post: the field we are editing with its new value 
    122         var args = {}; 
    123         if ($(this).attr('value')) { 
    124             args[$(this).attr('name')] = $(this).attr('value'); 
    125         } else { 
    126             args[$(this).attr('name')] = ''; 
    127         } 
    128  
    129         // ajax post to edit the object 
    130         $.post(getUrl(cell), args, function(data) { 
    131             // display the new value in the page 
    132             $(cell).html(data); 
    133  
    134             // in case of validation error 
    135             setupForm(cell, single); 
    136         }); 
    137     } 
    138 } 
     174} 
     175 
    139176 
    140177$(document).ready(function() { 
     178    // activate only on change-list pages 
    141179    if ($('body').attr('class') != 'change-list') return; 
    142180 
    143     $('#content h1').append('<ul class="messagelist"><li>Click any field to edit it in place</li></ul>'); 
    144  
    145     // on click: edit 
    146     $('td, th').click(editField); 
     181    // show help message 
     182    $('#content h1').append(MESSAGE); 
     183 
     184    // on click on a table cell: edit 
     185    $('tbody td, tbody th').click(edit); 
    147186    // when clicking on a link, do not edit 
    148     $('td a, th a').click(function(event) { event.stopPropagation(); }); 
    149  
    150     // add checkboxes to each row 
    151     $('tr').prepend($('<th><input type="checkbox"/></th>')); 
     187    $('tbody td a, tbody th a').click(stopPropagation); 
     188 
     189    // add checkboxes to each row and save the links 
     190    $('tr').each(function() { 
     191        var url = window.location.href + $(this).find('a').attr('href'); 
     192        url = url.replace(ADMIN_URL, ADMINEDIT_URL); 
     193 
     194        $(this).prepend($('<th><a class="adminedit_link" href="'+url+'"></a><input type="checkbox"/></th>')); 
     195    }); 
    152196 
    153197    // select/deselect all 
  • unicoders/trunk/unicoders/adminedit/templates/adminedit/field_view.html

    r75 r77  
    1 {{ field }} 
     1{% ifequal field None %}(None){% else %}{{ field }}{% endifequal %} 
  • unicoders/trunk/unicoders/adminedit/urls.py

    r75 r77  
    22 
    33urlpatterns = patterns('unicoders.adminedit.views', 
    4     (r'^edit/(?P<type>.+)/(?P<id>[0-9]+)/(?P<field>.+)$', 'field_edit'), 
     4    (r'^(?P<app>.+)/(?P<model>.+)/(?P<id>[0-9]+)/(?P<field>.+)$', 'field_edit'), 
    55) 
  • unicoders/trunk/unicoders/adminedit/views.py

    r76 r77  
    44from django.contrib import admin 
    55 
    6 def field_edit(request, type, id, field): 
    7     c = ContentType.objects.get(name__exact=type).model_class() 
     6def field_edit(request, app, model, id, field): 
     7    c = ContentType.objects.get(app_label=app, model=model).model_class() 
    88    Form = forms.form_for_instance(c.objects.get(id=id)) 
    99 
     
    1717        form = Form(request.POST) 
    1818        o = c.objects.get(id=id) 
     19 
     20        # special case for boolean fields 
     21        if 'toggle' in request.POST: 
     22            setattr(o, field, request.POST['toggle'] == 'true') 
     23            o.save() 
     24            return field_view(o, field) 
     25 
    1926        try: 
    2027            setattr(o, field, form[field].field.clean(request.POST.get(field, None))) 
  • unicoders/trunk/unicoders/media/scripts/adminedit.js

    r76 r77  
     1var ADMIN_URL = '/admin/'; 
     2var ADMINEDIT_URL = '/adminedit/'; 
     3var THROBBER ='<img src="/media/images/throbber.gif" class="throbber"/>'; 
     4var MESSAGE = '<ul class="messagelist"><li>Click any field to edit it in place</li></ul>'; 
     5 
     6function stopPropagation(event) { event.stopPropagation(); } 
     7 
    18function getFieldId(cell) { 
    29    var cell = $(cell); 
     
    1926} 
    2027 
    21 function getTypeName() { 
    22     return document.location.href.split('/').slice(-2, -1)[0]; 
    23 } 
    24 function getObjectId(cell) { 
    25     var id = $(cell).parent().find('a').attr('href'); 
    26     return id.substring(0, id.length-1); 
    27 } 
    28  
    2928function getUrl(cell) { 
    30     // build the url 
    31     var type = getTypeName(); 
    32     var id = getObjectId(cell); 
    33     var field = getFieldId(cell); 
    34     return '/adminedit/edit/'+type+'/'+id+'/'+field; 
     29    return $(cell).parent().find('a').attr('href') + getFieldId(cell); 
    3530} 
    3631 
     
    3833    return $(cell).parent().find('th input')[0].checked; 
    3934} 
    40 function editField() { 
     35 
     36function focusForm(cell) { 
     37    var form = $(cell).find('input, textarea, select'); 
     38    if (form.length > 0) form[0].focus(); 
     39} 
     40 
     41 
     42function edit() { 
     43    var cell = this; 
     44    var bool = null; 
     45 
     46    function editOne(c, b) { 
     47        if (b != null) { 
     48            editBooleanField(c, !b); 
     49        } else { 
     50            editField(c); 
     51        } 
     52    } 
     53 
     54    // special case for bool fields 
     55    if ($(cell).find('img').length > 0) bool = ($(cell).find('img').attr('alt') == 'True'); 
     56 
    4157    // if the row we are editing is selected 
    42     if (isRowSelected(this)) { 
     58    if (isRowSelected(cell)) { 
    4359        // do the same edit on all the other rows that are selected 
    44         getCellsInColumn(this).each(function() { 
    45             if (isRowSelected(this)) editSingleField.call(this, false); 
     60        getCellsInColumn(cell).each(function() { 
     61            if (isRowSelected(this)) editOne(this, bool); 
    4662        }); 
    4763    } else { 
    48         editSingleField.call(this, true); 
    49     } 
    50 } 
    51  
    52 function setupForm(target, single) { 
    53     var form = $(target).find('input, textarea, select'); 
     64        editOne(cell, bool); 
     65        focusForm(cell); 
     66    } 
     67} 
     68 
     69function save() { 
     70    var form = this; 
     71    var cell = $(form).parent(); 
     72    // if the row we are editing is selected 
     73    if (isRowSelected(cell)) { 
     74        // save all the other rows that are selected 
     75        getCellsInColumn(cell).each(function() { 
     76            if (isRowSelected(this)) saveField($(this).find('input, textarea, select')); 
     77        }); 
     78    } else { 
     79        saveField(form); 
     80        focusForm(cell); 
     81    } 
     82} 
     83 
     84function editBooleanField(cell, value) { 
     85    var args = {}; 
     86    args['toggle'] = value; 
     87 
     88    // throbber 
     89    $(cell).append(THROBBER); 
     90 
     91    $.post(getUrl(cell), args, function(data) { 
     92        var img = $($(cell).find('img')[0]); 
     93 
     94        data = data.split('\n')[0]; 
     95 
     96        if ((data == 'True') || (data == 'False')) { 
     97            img.attr('alt', data); 
     98            // remove the throbber 
     99            $(cell).find('img.throbber').remove(); 
     100        } 
     101 
     102        if (data == 'True') { 
     103            img.attr('src', img.attr('src').replace('-no', '-yes')); 
     104        } else if (data == 'False') { 
     105            img.attr('src', img.attr('src').replace('-yes', '-no')); 
     106        } 
     107    }); 
     108} 
     109 
     110function editField(cell) { 
     111    // throbber 
     112    $(cell).append(THROBBER); 
     113 
     114    // ajax request for the form widget 
     115    $.get(getUrl(cell), function(data) { 
     116        // insert the ajax response in the page 
     117        $(cell).html(data); 
     118        setupForm(cell); 
     119    }); 
     120} 
     121 
     122function saveField(form) { 
     123    var cell = $(form).parent(); 
     124 
     125    // throbber 
     126    cell.append(THROBBER); 
     127 
     128    // just one argument to the post: the field we are editing with its new value 
     129    var args = {}; 
     130    if ($(form).attr('value')) { 
     131        args[$(form).attr('name')] = $(form).attr('value'); 
     132    } else { 
     133        args[$(form).attr('name')] = ''; 
     134    } 
     135 
     136    // ajax post to edit the object 
     137    $.post(getUrl(cell), args, function(data) { 
     138        // display the new value in the page 
     139        $(cell).html(data); 
     140 
     141        // in case of validation error 
     142        setupForm(cell); 
     143    }); 
     144} 
     145 
     146function setupForm(cell) { 
     147    var form = $(cell).find('input, textarea, select'); 
    54148    if (form.length == 0) return; 
    55149 
    56150    // do not start the edit again if we click on a form element 
    57     form.click(function(event) { event.stopPropagation(); event.preventDefault(); }); 
     151    form.click(stopPropagation); 
    58152    // on blur: save 
    59     form.blur(function() { saveField.call(this, single); }); 
     153    form.blur(save); 
    60154    // on enter: save 
    61155    form.keypress(function(event) { 
    62         if (event.keyCode == 13) saveField.call(this, single); 
    63     }); 
    64  
    65  
     156        if (event.keyCode == 13) save.call(this); 
     157    }); 
     158 
     159    // edit all selected fields simultaneously 
    66160    function changeField() { 
    67161        function innerChangeField() { 
    68             var cell = $(target); 
    69             if (target.tagName == 'A') cell = $(target).parent(); 
    70162            getCellsInColumn(cell).each(function() { 
    71163                if (isRowSelected(this)) { 
     
    75167            }); 
    76168        }; 
    77         setTimeout(innerChangeField, 10); 
     169        // let the current element edit before updating the other ones 
     170        setTimeout(innerChangeField, 1); 
    78171    } 
    79172    form.change(changeField); 
    80173    form.keypress(changeField); 
    81  
    82     // focus on the new form widget 
    83     if (single) form[0].focus(); 
    84 } 
    85  
    86 function editSingleField(single) { 
    87     var target = this; 
    88     // keep the link if present 
    89     if ($(target).find('a').length > 0) { 
    90         target = $(this).find('a')[0]; 
    91     } 
    92  
    93     // throbber 
    94     $(target).append('<img src="/media/images/throbber.gif"/>'); 
    95  
    96     // ajax request for the form widget 
    97     $.get(getUrl(this), function(data) { 
    98         // insert the ajax response in the page 
    99         $(target).html(data); 
    100  
    101         setupForm(target, single); 
    102     }); 
    103 } 
    104  
    105 function saveField(single) { 
    106     var cell = $(this).parent(); 
    107 //    var target = cell; 
    108 //    if (cell[0].tagName == 'SPAN') cell = cell.parent(); 
    109  
    110     if (!single) { 
    111         var column = getCellsInColumn(cell); 
    112         var form = this; 
    113         column.each(function() { 
    114             if (isRowSelected(this)) saveField.call($(this).find('input, textarea, select'), true); 
    115         }); 
    116     } else { 
    117  
    118         // throbber 
    119         cell.append('<img src="/media/images/throbber.gif"/>'); 
    120  
    121         // just one argument to the post: the field we are editing with its new value 
    122         var args = {}; 
    123         if ($(this).attr('value')) { 
    124             args[$(this).attr('name')] = $(this).attr('value'); 
    125         } else { 
    126             args[$(this).attr('name')] = ''; 
    127         } 
    128  
    129         // ajax post to edit the object 
    130         $.post(getUrl(cell), args, function(data) { 
    131             // display the new value in the page 
    132             $(cell).html(data); 
    133  
    134             // in case of validation error 
    135             setupForm(cell, single); 
    136         }); 
    137     } 
    138 } 
     174} 
     175 
    139176 
    140177$(document).ready(function() { 
     178    // activate only on change-list pages 
    141179    if ($('body').attr('class') != 'change-list') return; 
    142180 
    143     $('#content h1').append('<ul class="messagelist"><li>Click any field to edit it in place</li></ul>'); 
    144  
    145     // on click: edit 
    146     $('td, th').click(editField); 
     181    // show help message 
     182    $('#content h1').append(MESSAGE); 
     183 
     184    // on click on a table cell: edit 
     185    $('tbody td, tbody th').click(edit); 
    147186    // when clicking on a link, do not edit 
    148     $('td a, th a').click(function(event) { event.stopPropagation(); }); 
    149  
    150     // add checkboxes to each row 
    151     $('tr').prepend($('<th><input type="checkbox"/></th>')); 
     187    $('tbody td a, tbody th a').click(stopPropagation); 
     188 
     189    // add checkboxes to each row and save the links 
     190    $('tr').each(function() { 
     191        var url = window.location.href + $(this).find('a').attr('href'); 
     192        url = url.replace(ADMIN_URL, ADMINEDIT_URL); 
     193 
     194        $(this).prepend($('<th><a class="adminedit_link" href="'+url+'"></a><input type="checkbox"/></th>')); 
     195    }); 
    152196 
    153197    // select/deselect all