Changes between Version 3 and Version 4 of AjaxDojoFormSub


Ignore:
Timestamp:
Jul 25, 2006, 8:15:45 AM (18 years ago)
Author:
Alexander Solovyov
Comment:

Info was destroyed in version 3. Fixed.

Legend:

Unmodified
Added
Removed
Modified
  • AjaxDojoFormSub

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