1AJAX with jQuery
2================
3
4`jQuery`_ is a small JavaScript library commonly used to simplify working
5with the DOM and JavaScript in general.  It is the perfect tool to make
6web applications more dynamic by exchanging JSON between server and
7client.
8
9JSON itself is a very lightweight transport format, very similar to how
10Python primitives (numbers, strings, dicts and lists) look like which is
11widely supported and very easy to parse.  It became popular a few years
12ago and quickly replaced XML as transport format in web applications.
13
14.. _jQuery: https://jquery.com/
15
16Loading jQuery
17--------------
18
19In order to use jQuery, you have to download it first and place it in the
20static folder of your application and then ensure it's loaded.  Ideally
21you have a layout template that is used for all pages where you just have
22to add a script statement to the bottom of your ``<body>`` to load jQuery:
23
24.. sourcecode:: html
25
26   <script src="{{ url_for('static', filename='jquery.js') }}"></script>
27
28Another method is using Google's `AJAX Libraries API
29<https://developers.google.com/speed/libraries/>`_ to load jQuery:
30
31.. sourcecode:: html
32
33    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
34    <script>window.jQuery || document.write('<script src="{{
35      url_for('static', filename='jquery.js') }}">\x3C/script>')</script>
36
37In this case you have to put jQuery into your static folder as a fallback, but it will
38first try to load it directly from Google. This has the advantage that your
39website will probably load faster for users if they went to at least one
40other website before using the same jQuery version from Google because it
41will already be in the browser cache.
42
43Where is My Site?
44-----------------
45
46Do you know where your application is?  If you are developing the answer
47is quite simple: it's on localhost port something and directly on the root
48of that server.  But what if you later decide to move your application to
49a different location?  For example to ``http://example.com/myapp``?  On
50the server side this never was a problem because we were using the handy
51:func:`~flask.url_for` function that could answer that question for
52us, but if we are using jQuery we should not hardcode the path to
53the application but make that dynamic, so how can we do that?
54
55A simple method would be to add a script tag to our page that sets a
56global variable to the prefix to the root of the application.  Something
57like this:
58
59.. sourcecode:: html+jinja
60
61   <script>
62     $SCRIPT_ROOT = {{ request.script_root|tojson }};
63   </script>
64
65
66JSON View Functions
67-------------------
68
69Now let's create a server side function that accepts two URL arguments of
70numbers which should be added together and then sent back to the
71application in a JSON object.  This is a really ridiculous example and is
72something you usually would do on the client side alone, but a simple
73example that shows how you would use jQuery and Flask nonetheless::
74
75    from flask import Flask, jsonify, render_template, request
76    app = Flask(__name__)
77
78    @app.route('/_add_numbers')
79    def add_numbers():
80        a = request.args.get('a', 0, type=int)
81        b = request.args.get('b', 0, type=int)
82        return jsonify(result=a + b)
83
84    @app.route('/')
85    def index():
86        return render_template('index.html')
87
88As you can see I also added an `index` method here that renders a
89template.  This template will load jQuery as above and have a little form where
90we can add two numbers and a link to trigger the function on the server
91side.
92
93Note that we are using the :meth:`~werkzeug.datastructures.MultiDict.get` method here
94which will never fail.  If the key is missing a default value (here ``0``)
95is returned.  Furthermore it can convert values to a specific type (like
96in our case `int`).  This is especially handy for code that is
97triggered by a script (APIs, JavaScript etc.) because you don't need
98special error reporting in that case.
99
100The HTML
101--------
102
103Your index.html template either has to extend a :file:`layout.html` template with
104jQuery loaded and the `$SCRIPT_ROOT` variable set, or do that on the top.
105Here's the HTML code needed for our little application (:file:`index.html`).
106Notice that we also drop the script directly into the HTML here.  It is
107usually a better idea to have that in a separate script file:
108
109.. sourcecode:: html
110
111    <script>
112      $(function() {
113        $('a#calculate').bind('click', function() {
114          $.getJSON($SCRIPT_ROOT + '/_add_numbers', {
115            a: $('input[name="a"]').val(),
116            b: $('input[name="b"]').val()
117          }, function(data) {
118            $("#result").text(data.result);
119          });
120          return false;
121        });
122      });
123    </script>
124    <h1>jQuery Example</h1>
125    <p><input type=text size=5 name=a> +
126       <input type=text size=5 name=b> =
127       <span id=result>?</span>
128    <p><a href=# id=calculate>calculate server side</a>
129
130I won't go into detail here about how jQuery works, just a very quick
131explanation of the little bit of code above:
132
1331. ``$(function() { ... })`` specifies code that should run once the
134   browser is done loading the basic parts of the page.
1352. ``$('selector')`` selects an element and lets you operate on it.
1363. ``element.bind('event', func)`` specifies a function that should run
137   when the user clicked on the element.  If that function returns
138   `false`, the default behavior will not kick in (in this case, navigate
139   to the `#` URL).
1404. ``$.getJSON(url, data, func)`` sends a ``GET`` request to `url` and will
141   send the contents of the `data` object as query parameters.  Once the
142   data arrived, it will call the given function with the return value as
143   argument.  Note that we can use the `$SCRIPT_ROOT` variable here that
144   we set earlier.
145
146Check out the :gh:`example source <examples/javascript>` for a full
147application demonstrating the code on this page, as well as the same
148thing using ``XMLHttpRequest`` and ``fetch``.
149