Changes between Version 2 and Version 3 of AjaxDojoFormSub


Ignore:
Timestamp:
Jul 21, 2006, 3:29:09 PM (18 years ago)
Author:
germish@…
Comment:

mention changeset 3232 and django.utils.simplejson

Legend:

Unmodified
Added
Removed
Modified
  • AjaxDojoFormSub

    v2 v3  
    1 
    21{{{
    32#!html
     
    5049{{{
    5150sudo python easy_install simplejson
     51}}}
     52
     53update: changeset [http://code.djangoproject.com/changeset/3232 3232] now offers v1.3 of simplejson in django's utils, so you do not need to download and install simplejson -- just use django.utils.simplejson.
     54{{{
     55from django.utils import simplejson #in replace of import simple_json
    5256}}}
    5357
     
    126130  function sendFormCallback(type, data, evt)
    127131    {
    128     if (type == 'error')
    129         alert('Error when retrieving data from the server!');
    130     else
    131         // de code the simpleJson answer from django ''details'' method.
    132         // it populates a Js array ! straigth so cool !
    133         arrayData = dojo.json.evalJson(data);
    134         // now we update the html using the css id as a pointer to the part
    135         // we want to update
    136         dojo.byId("mark_total").innerHTML = arrayData[1];
    137         dojo.byId("mark_message").innerHTML = arrayData[2];
    138         dojo.byId("mark_status").innerHTML = arrayData[3];
    139         // and the fancy fading effect
    140         dojo.lfx.html.highlight("mark_status", [255, 151, 58], 700).play(300);
    141     }
    142    
    143     function init()
    144     {
    145         var sendFormButton = dojo.byId('sendFormButton');
    146         dojo.event.connect(sendFormButton, 'onclick', 'sendForm')
    147     }
    148  
    149     dojo.addOnLoad(init);
    150        
    151 </script>
    152 }}}
    153 
    154 the following ''HTML code'' just comes after the upper code snipset.
    155 
    156 {{{
    157 [... total mark get updated, lets put css id="mark_total" ...]
    158 {% if r.total_mark  %}<li><b>Score</b>: <span id="mark_total">{{ r.total_mark }}</span>/5</li>{% endif %}
    159 [....]
    160 {% if not user.is_anonymous %}
    161     {% ifnotequal user.id r.owner_id %}
    162         <form enctype="multipart/form-data" id="myForm" method="post">
    163             <span id="mark_message">{{mark_message}}</span>
    164                <select name="select_mark">
    165                     <option value ="1" {% ifequal my_mark 1 %} selected {% endifequal %}>1</option>
    166                     <option value ="2" {% ifequal my_mark 2 %} selected {% endifequal %}>2</option>
    167                     <option value ="3" {% ifequal my_mark 3 %} selected {% endifequal %}>3</option>
    168                     <option value ="4" {% ifequal my_mark 4 %} selected {% endifequal %}>4</option>
    169                     <option value ="5" {% ifequal my_mark 5 %} selected {% endifequal %}>5</option>
    170                </select>
    171        </form>
    172       <button id="sendFormButton">Notez</button>
    173       <br/>
    174       <span id="mark_status">{{ mark_status }}</span>
    175      {% endifnotequal %}
    176 {% endif %}
    177 }}}
    178 
    179 And, voila.
    180 
    181 To have a demo use guest as login, guest as password here [http://ozserver.no-ip.com:345] or if not working here [http://www.cefinban.net].
    182 Go to index and pick a recipe, update the rating.
    183 
    184 You can also have a look at the screenshot here :  [http://ozserver.no-ip.com/~greg/images/ajaxdjango.png]
    185 
    186 == Dreamhost and Simplejson ==
    187 
    188 If you are using dreamhost for hosting please be aware that simplejson is not installed.
    189 Instead you will have to install the source of simplejson in a folder in your home directory eg /proz/json/simple_json
    190 The simple_json directory contains the required __init__.py for it to be loaded as a python module.
    191 
    192 Then in your ~/.bash_profile add the directory to your python path like below.
    193 
    194 {{{
    195 export PYTHONPATH=$PYTHONPATH:$HOME/django/django_src:$HOME/django/django_projects:$HOME/progz/json
    196 }}}
    197 
    198 That will allow yout to use simpl_json in python shell.
    199 But '''dont forget''' to change django.fcgi !
    200 Add
    201 {{{
    202 sys.path +=['/home/coulix/progz/json']
    203 }}}
    204 log out/in and try import simple_json (or simplejson depends on what source you picked)
    205 
    206 {{{
    207 #!html
    208 <a name="P2"><h1>Handling the form when JavaScript is deactivated.</h1></a>
    209 }}}
    210 If a user has deactivated his browser's javascript support, or is using a text mode browser, we need a way of making the previous rating button submit the rating to the server which should this time return an html template instead of data to the Ajax call.
    211 
    212 == Updating the form HTML (details.html template) ==
    213 This time we put a submit type input inside the form instead of the button type in part 1.
    214 type="submit" as indicates its name, submits the form to the server, we will need a way of stopping this behavior using javaScript.
    215 
    216 {{{
    217 <form  enctype="multipart/form-data" id="myForm" method="post">
    218         <span id="mark_message">{{mark_message}}</span>
    219         <select name="select_mark">
    220                 [...]
    221         </select>
    222         <input id="sendFormButton" type="submit" value="Notez" />
    223 </form>
    224 }}}
    225 
    226 Now, how can we tell our details method in view.py to know if it comes from a normal submit request or an Ajax request ?
    227 Two solutions,
    228 
    229 The '''first''' uses a hidden variable in form.html and an added content element in the JS part.
    230 
    231 {{{
    232     function sendForm()
    233     {
    234      dojo.byId("mark_status").innerHTML = "Loading ...";
    235      dojo.io.bind({
    236                     url: '.',
    237                     handler: sendFormCallback,
    238                     content: {"js", "true"},
    239                     formNode: dojo.byId('myForm')
    240                 });
    241     }
    242 
    243 
    244 [...]
    245 <form  enctype="multipart/form-data" id="myForm" method="post">
    246 [...]
    247 <input type="hidden" name="js" value="false">
    248 </form>
    249 }}}
    250 
    251 With this, in our django method in view.py we can test for request["js"]=="true" it would means that Js is activatd and we return the appropriate answer to the Ajax request.
    252 
    253 The '''second''' uses the url to pass a new variable ajax_or_not to the detail method.
    254 
    255 {{{
    256 #!python
    257 def details(request, r_slug, r_cat, ajax_or_not=None):
    258 [...]
    259 }}}
    260 
    261 We modify the url.py to accept this new parameter.
    262 {{{
    263 #!python
    264 (r'^recettes/(?P<r_cat>[-\w]+)/(?P<r_slug>[-\w]+)/(?P<ajax_or_not>.*)$', 'cefinban.recettes.views.details'),
    265 }}}
    266 
    267 The dojo binding needs to append a variable to the original document url, to make ajax_or_not not None.
    268 
    269 {{{
    270     function sendForm()
    271     {
    272      dojo.byId("mark_status").innerHTML = "Loading ...";
    273      dojo.io.bind({
    274                     url: './ajax/',
    275                     handler: sendFormCallback,
    276                     formNode: dojo.byId('myForm')
    277                 });
    278     }
    279 }}}
    280 
    281 == New details method in view.py ==
    282 
    283 We just need to test for the existence of ajax_or_not
    284 
    285 {{{
    286 #!python
    287 def details(request, r_slug, r_cat, ajax_or_not=None):
    288 [...]
    289         if request.POST:
    290                 [...] same as part 1
    291                 # except here we check ajax_or_not
    292                 if  ajax_or_not:
    293                         # use json for python js exchange
    294                         # it was a french string, if we dont't use unicode
    295                         # the result at the output of json in Dojo is wrong.
    296                         message = unicode( message, "utf-8" )
    297                         jsonList = simple_json.dumps((my_mark, total, form_message ,message))
    298                         return HttpResponse(jsonList)
    299 
    300         return render_to_response('recettes/details.html', {'r': r, 'section':'index',
    301                  'mark_status':message , 'mark_message':form_message, 'my_mark': my_mark},
    302                   context_instance=RequestContext(request),)
    303 }}}
    304 
    305 {{{
    306 #!html
    307 <a name="P3"><h1>Fixing the frozen fading when user resend the form without waiting for the first fading to end.</h1></a>
    308 }}}
    309 If you haven't realised yet, if two or more calls are sent to the javascript function sendForm in a short time, the fading effect of the current sendForm Callback method might get stuck / froze / bugged.
    310 We need a way of avoiding this by desactivating the connection between the submit button and the sendForm method while the fading '''animation''' is active.
    311 Thanks Dojo there is such things ! in two lines of code its done.
    312 
    313 
    314 {{{
    315 function sendFormCallback(type, data, evt)
    316     {
    317        [...as before ...]
    318         // and the fancy fading effect
    319        
    320         // first disconnect the listener !
    321         dojo.event.disconnect(sendFormButton, 'onclick', 'sendForm');
    322         // assign our fading effect to an anim variable.
    323         var anim = dojo.lfx.html.highlight("mark_status", [255, 151, 58], 700).play(300);
    324         // When this anim is finish, reconnect
    325         dojo.event.connect(anim, "onEnd", function() {  dojo.event.connect(sendFormButton, 'onclick', 'sendForm'); });
    326     }
    327 }}}
    328 
    329 how nice is this !
    330 Careful, while talking about how to fix the problem using onEnd in Dojo IRC chanel, they realised play() method didnt behave properly and updated it to react to onEnd and such.
    331 su you need at least revision '''4286'''.
    332 Update your dojo source
    333 
    334 {{{
    335 svn co http://svn.dojotoolkit.org/dojo/trunk dojo
    336 }}}
    337 
    338 
    339 
    340 
    341 '''Note'''  It might be completely wrong.
    342 More questions / complaints: coulix@gmail.com
    343 
Back to Top