Warning: Can't synchronize with repository "(default)" (Unsupported version control system "svn": No module named svn). Look in the Trac log for more information.

Changes between Version 1 and Version 2 of FancyStatus


Ignore:
Timestamp:
01/04/06 09:29:50 (13 years ago)
Author:
spleeman@…
Comment:

Removed stale text and linked to original article

Legend:

Unmodified
Added
Removed
Modified
  • FancyStatus

    v1 v2  
    1 from splee.blog by Lee McFadden 
     1from [http://www.splee.co.uk/ splee.blog] by Lee McFadden 
    22 
    3 I like using ajaxy interfaces in my web apps, and as such I also like the type of status messages that you can achieve using Mochikit. However, sometimes you need to pass a status message between pages (when you’re using raise cherrypy.HTTPRedirect() for example) and I just don’t like having two different ways to display things. 
    4  
    5 To dissolve my perfectionist worries that the standard tg_flash message in a div just doesn’t cut it, I looked at ways of making the message look the same as a status message from my ajax calls. 
    6  
    7 == Preparing the way == 
    8  
    9 First, I have my simple div to contain the message within the body tags of my master.kid: 
    10  
    11 {{{ 
    12 <div id="statusmessage"></div> 
    13 }}} 
    14  
    15 Then I created the CSS to make this message box look nice: 
    16  
    17 {{{ 
    18 #statusmessage { 
    19         position: absolute; 
    20         top: -1px; 
    21         left:200px; 
    22         right: 200px; 
    23         z-index: 5000; 
    24 } 
    25  
    26 #statusmessage div { 
    27         width: 400px; 
    28         margin: 0px auto; 
    29         height: 50px; 
    30         padding: 35px 10px 10px 55px; 
    31         background-repeat: no-repeat; 
    32         background-position: left; 
    33         font-size: 18px; 
    34  opacity: .75; 
    35         filter: alpha(opacity=75); 
    36 } 
    37  
    38 #statusmessage div.success { 
    39         background-color: #99CC99; 
    40         border: 1px solid #006633; 
    41         background-image: url("/static/images/dialog-information.png"); 
    42 } 
    43  
    44 #rdsmsg div.error { 
    45         background-color: #C00; 
    46         border: 1px solid #600; 
    47         background-image: url("/static/images/dialog-error.png"); 
    48 } 
    49 }}} 
    50  
    51 Note the last two blocks of CSS. The background image, and colours of the status message can be modified depending on the type of status message. The only ones I’ve defined here are ’success’ and ‘error’, but you can have any number of message types. 
    52  
    53 == The Code == 
    54  
    55 The javascript workhorse to control the display of these messages is a simple function using the spanky Mochikit functions available to you. 
    56 {{{ 
    57 function displayStatusMessage(status, msg) { 
    58  
    59  swapDOM("statusmessage", DIV({'id': 'statusmessage'}, DIV({'class': status}, msg))); 
    60  
    61  callLater(5, swapDOM, "statusmessage", DIV({'id': 'statusmessage'}, null)); 
    62  
    63 } 
    64 }}} 
    65  
    66 What this function does is to swap out your empty statusmessage div for one packed with the info you give it. It then waits for 5 seconds before making it empty again. 
    67  
    68 As you can see, providing you have the CSS for the status type, you can pass any type of status that you can think of. 
    69 Using with AJAX calls 
    70  
    71 To use these status messages with your AJAX calls is a cinch. Here is an example callback function from the app I’m developing: 
    72  
    73 {{{ 
    74 function saveHandler(result) { 
    75  
    76  data = evalJSONRequest(result); 
    77   
    78  if (data['status'] == "success") { 
    79   
    80  displayRdsmsg(data['status'], data['msg']); 
    81  getElement('articleId').value = data['id']; 
    82   
    83  } else { 
    84  if(data['status'] == "error") { 
    85  displayRdsmsg(data['status'], data['msg']); 
    86  } else { 
    87  displayRdsmsg('fatal', 'There was an unknown error!'); 
    88  } 
    89  } 
    90 } 
    91 }}} 
    92  
    93 The result parameter to the saveHandler function is an XMLHttpRequest object as I’m POST’ing the request to the server rather than using GET. If you want to use Mochikit’s loadJSONDoc() function to handle the request it returns a javascript array for you so you just leave the first line of the above function out and change the parameter name from result to data. 
    94  
    95 This will provide you with a nice little message everytime you save a document, provided you return the variables status and msg along with the rest of your data in your controller function. 
    96 Using with tg_flash 
    97  
    98 This is all fine and dandy when you’re displaying a status message after an async callback as you have some JSON to stuff the status message with. “How do I use this with tg_flash”, I hear you cry? 
    99  
    100 == JSON == 
    101  
    102 Since JSON is native to JavaScript you can actually create javascript objects from any JSON formatted string. Considering how close JSON syntax is to python’s own lists and dictionaries, you should have no problem creating a string in your controller and passing it to tg_flash. 
    103  
    104 To provide an example I’ve created a controller function called testflash in my app. We need to import a few extras in your controllers.py: 
    105  
    106 {{{ 
    107 from turbogears.jsonify import jsonify 
    108 import json 
    109 }}} 
    110  
    111 And the example for transferring a JSON string in tg_flash: 
    112  
    113 {{{ 
    114 @turbogears.expose() 
    115 def testflash(self): 
    116  flashData = {"status": "error", "msg": "The page was NOT saved!"} 
    117  turbogears.flash(json.write(jsonify(flashData))) 
    118  raise cherrypy.HTTPRedirect(turbogears.url("/")) 
    119 }}} 
    120  
    121 The key here is the string passed to turbogears.flash(). This is a JSON string. JavaScript can recognise this string and build a javascript object out of it. To do this I have the following code within my master.kid’s head tags: 
    122  
    123 {{{ 
    124 <script type="text/javascript"> 
    125  function flashedStatusMessage() { 
    126  flashData = getElement('flashTransport').value; 
    127  statusmsg = eval('(' + flashData + ')'); 
    128  displayStatusMessage(statusmsg['status'], statusmsg['msg']); 
    129  } 
    130  addLoadEvent(flashedStatusMessage); 
    131 </script> 
    132 }}} 
    133  
    134 I then need to add a hidden element in my master.py’s body tags: 
    135 {{{ 
    136 <input type="hidden" id="flashTransport" name="flashTransport" py:attrs="value=tg_flash" /> 
    137 }}} 
    138 The script will check for the value of the flashTransport element on every page load. If it fails to find anything there is no message, but if tg_flash has been called the value (already nicely escaped by Kid) will be used as the data for the status message. 
    139  
    140 You can use this method to insert extremely complex status and error messages into your app, not to mention a myriad of options for styling said messages. You are only limited by your ability to create JSON strings to feed tg_flash and your ability to translate those JSON strings into DOM elements using Mochikit. 
    141  
    142 Here are some screenshots of the (roughly) styled messages when they pop up in my app: 
    143  
    144  
    145 http://node1.lmsrv.com/images/pretty-tg-flash.png 
    146 http://node1.lmsrv.com/images/pretty-tg-flash2.png 
    147  
     3[http://www.splee.co.uk/2005/11/23/fancy-status-messages-using-tg_flash/ Full article here] 
    1484 
    1495'''posted to wiki by reflog''' 
     6 
     7'''Linked to blog by Lee McFadden''' - I have made a few little adjustments, and will probably continue to do so.  I've simply linked this straight to my blog :)