Submit Blog  RSS Feeds
Showing posts with label javascript. Show all posts
Showing posts with label javascript. Show all posts

Monday, September 24, 2012

Logging JavaScript exceptions using raven-js and sentry.

Let's face it, its hard to obtain 100% unit-test code coverage, likewise it's nearly impossible to implement functional tests for all possible scenarios. A good way of recognizing problems and locating them is logging exceptions and other informative messages. For small projects logging to std out/err or files is fine, but if there are hundreds of people exploiting your application every minute you should think of a more scalable solution.

Sentry is a good option, it's a real-time event logging platform that may be set-up as a standalone application. Other pros are:
  • support of different levels of logging / dynamic filtering
  • logging data from many independent projects
  • presistent log storing (database)
  • user privilege configuration / email notification
  • there are clients for many popular programming languages
  • it's based on python/django
  • it's based on python/django
  • it's based on python/django
  • ....
I can go on like this forever :-) You can easily install sentry via pip.

~ virtualenv --no-site-packages sentry_env && cd sentry_env
~ source bin/activate
(sentry_env) ~ pip install sentry
(sentry_env) ~ sentry init

Now all you have to configure database access and other important parameters, check out the sentry configuration guide for more information.

But let's get back to the main thought. Among programming languages that have clients for sentry there is also JavaScript. This wouldn't be a surprise if not for the fact that (besides node.js) JS is usually executed on the client side (web browser). Raven-js (don't confuse it the client for RavenDB) can log messages / catch exceptions and send them via AJAX requests to your sentry application. In order to set up the logging script you should first configure sentry and create a project and obtain generated project public key. Then use the following code:




Setting up raven-js and observing how your scripts crash on IE is just priceless :-)

~KR


Thursday, August 30, 2012

Passing django variables to javascript via templates

I can fairly say, that reasonable web applications can't exist without a bit of javascript. We all remember those static web pages that were popular in the late 90'. Well their time is up, professional websites frontend is built using HTML/XHTML/HTML5 + CSS + JS (sometimes Flash).

AJAX requests or newer synchronous pull/push methods enable achieving some dynamic connectivity between frontends and backends. It is also possible to pass some initialization data this way, however if your website architecture is not a real-time client-server (ex. WebSockets) this may be inefficient.

A good practice is initializing JS variables along with rendering pages, so additional initialization request are not required. A simple way of implementing this mechanism is passing JSON encoded data to the template and decoding it in JavaScript. Lets implement the appropriate django view:

def init_js_template(request):
    import json
    json_data = json.dumps({'test' : '12345', 'arr' : [1,2,3]})
    return render_to_respons('init_json.html', {'json_data':json_data})

And the corresponding javascript initialization in the init_json.html template:



This way you will save some resources by reducing the number AJAX calls. Just keep in mind that this will only work for arrays/dictionaries containing primitive types or other arrays.

~KR

Sunday, July 29, 2012

A quick look into HTML5 canvas tag

Lately I've experimenting with the new HTML5 features. There are many new tags, and attributes that add new functionality to existing tags. I wouldn't want to get to much into a general preview of these elements, instead I want to focus on single tag: <canvas>. A canvas element/property frequently appears in high level GUI designing programs or interfaces, it allows to draw custom graphics/primitives on a panel. The HTML5 canvas semantic is similar: it allows drawing graphics on the fly! Yes, no more CSS tricks to get an animation running effectively, now all you need is a browser supporting HTML5 and some basic JS knowledge.


Canvas and 2D graphics usually are connected with games, so after getting familiar with some basic concepts I started implementing a simple game - tetris similar. Here's what I have so far:





The currently implemented mechanics include:
  • falling bricks (1 type)
  • brick stacking (if one lands on another)
  • moving bricks left/right (arrow keys, it may not work via iframe)
The current code is available at http://boty.vipserv.org/tetris/tetris/tetris.html

Feel free to have a peek at the code, it's far from being tidy - this was just a fast canvas experiment.

The most popular browsers support HTML5, so I don't see any disadvantages in using it in day to day programming.

~KR

Thursday, July 19, 2012

Frontend number formating - thousands separators and rounding

It's good for a backend developer to do some JS scripting from time to time. Usually this scripting considers the user interface or other presentation mechanisms. Everybody knows that a good user interface has a great impact for attracting people to use your service.

Let's skip positioning/css stuff and move along to data presentation. Usually there is a difference between the data we actually process and the data shown to users. So we have a variable containing the cost of some imaginary service, i.e. 4231.1578. This looks just like an old-school float representation - and in fact it is. So whats wrong with the users?... oops... I mean why is  this representation not friendly to users?

Firstly, a common decimal delimiter for European countries is a comma, not a dot - we should respect it.

Secondly, humans do not process text the way machines - the larger the presented amount, the longer it takes to evaluate its value, or even the order of magnitude. Thats why you should provide thousands separators, all in all we get something like this: 4.231,1578

Now all it takes round the value a bit, we don't need so many decimal places. Below the code that converts your js floats to a formatted and readable string (val  is the float value, while dec_places is the number of decimal places).


1 function round_repr(val, dec_places){
2     var tmp = Math.round((val*Math.pow(10, dec_places))).toString();
3     tmp = tmp.slice(0, tmp.length-dec_places) + ',' + tmp.slice(tmp.length-dec_places, tmp.length);
4     var int_length = tmp.length - dec_places - 1 - 3;
5     var i = int_length;
6     for (i=int_length; i>0; i-=3){
7         tmp = tmp.slice(0, i) + "." + tmp.slice(i,tmp.length);
8     }
9    return tmp;
10   
11 }

~KR

Saturday, March 17, 2012

Cross-site ajax requests and security issues

Today I would like to share some of my experience regarding AJAX.

Ajax is commonly used to asynchronously fetch data from web applications deployed on the same domain (the user is not forced to reload the whole page while awaiting new data). So what happens when the the target URI domain differs from the domain on which the ajax script is running (cross-site)?

A web browser makes a request using the OPTIONS method and the following headers are set:


X-Requested-With: XMLHttpRequest
Origin: http://my.script.domain.com


The browser informs the requested resource about the type of the request (Ajax), and its origin (my.script.domain.com). If the target site accepts such requests it should attach the following response headers:

Access-Control-Allow-Origin: http://my.script.domain.com
Access-Control-Allow-Headers: X-Requested-With
Access-Control-Allow-Methods: GET, OPTIONS        
Access-Control-Max-Age: 3600

The first three headers determine the resource accessibility for certain requests: in this example only GET / OPTIONS Ajax requests from my.script.domain.com may be performed. The fourth header is related to response caching (seconds). So if the potential AJAX request meats these requirements, the browsers sends a following request using the appropriate method, and processes the response. 

If the response headers do not indicate that the request is allowed or there are no such headers at all (not all are obligatory), the second request is not performed. This security mechanism is implemented in all commonly used browsers... lets face it, without it AJAX would be a very dangerous technology...

Summing up: if you ever want to enable cross-site ajax requests for your site you must configure the Access-Control-Allow-* policy on the target server.


Tip: If you want your server to accept such requests from all sites, you may use the following policy:


Access-Control-Allow-Origin: *
Access-Control-Allow-Methods: GET, POST, DELETE, HEAD, OPTIONS        
Access-Control-Max-Age: 1209600


free counters