.. _javascript_modules: ============================= Customizing CKAN's JavaScript ============================= JavaScript code in CKAN is broken down into *modules*: small, independent units of JavaScript code. CKAN themes can add JavaScript features by providing their own modules. This tutorial will explain the main concepts involved in CKAN JavaScript modules and walk you through the process of adding custom modules to themes. .. seealso:: This tutorial assumes a basic understanding of CKAN plugins and templating, see: * :doc:`/extensions/index` * :doc:`/theming/templates` .. seealso:: This tutorial assumes a basic understanding of |javascript| and |jquery|, see: * `JavaScript on the Mozilla Developer Network `_ * `jQuery.com `_, including the `jQuery Learning Center `_ .. seealso:: :doc:`/contributing/string-i18n` How to mark strings for translation in your JavaScript code. -------- Overview -------- The idea behind CKAN's JavaScript modules is to keep the code simple and easy to test, debug and maintain, by breaking it down into small, independent modules. JavaScript modules in CKAN don't share global variables, and don't call each other's code. These JavaScript modules are attached to HTML elements in the page, and enhance the functionality of those elements. The idea is that an HTML element with a JavaScript module attached should still be fully functional even if JavaScript is completely disabled (e.g. because the user's web browser doesn't support JavaScript). The user experience may not be quite as nice without |JavaScript|, but the functionality should still be there. This is a programming technique known as *graceful degradation*, and is a basic tenet of web accessibility. In the sections below, we'll walk you through the steps to add a new JavaScript feature to CKAN - dataset info popovers. We'll add an info button to each dataset on the datasets page which, when clicked, opens a popover containing some extra information and user actions related to the dataset: .. image:: /images/example_theme_javascript_popover.png :alt: A dataset info popover -------------------------------- Initializing a JavaScript module -------------------------------- To get CKAN to call some custom JavaScript code, we need to: 1. Implement a |javascript| module, and register it with CKAN. Create the file ``ckanext-example_theme/ckanext/example_theme_docs/assets/example_theme_popover.js``, with these contents: .. literalinclude:: /../ckanext/example_theme_docs/v16_initialize_a_javascript_module/assets/example_theme_popover.js :language: javascript This bit of |javascript| calls the ``ckan.module()`` function to register a new JavaScript module with CKAN. ``ckan.module()`` takes two arguments: the name of the module being registered (``'example_theme_popover'`` in this example) and a function that returns the module itself. The function takes two arguments, which we'll look at later. The module is just a |javascript| object with a single attribute, ``initialize``, whose value is a function that CKAN will call to initialize the module. In this example, the initialize function just prints out a confirmation message - this |javascript| module doesn't do anything interesting yet. .. note:: |javascript| module names should begin with the name of the extension, to avoid conflicting with other modules. See :ref:`avoid name clashes`. .. note:: Each |javascript| module's ``initialize()`` function is called on `DOM ready `_. 2. Include the |javascript| module in a page, using Assets, and apply it to one or more HTML elements on that page. We'll override CKAN's ``package_item.html`` template snippet to insert our module whenever a package is rendered as part of a list of packages (for example, on the dataset search page). Create the file ``ckanext-example_theme/ckanext/example_theme_docs/templates/snippets/package_item.html`` with these contents: .. literalinclude:: /../ckanext/example_theme_docs/v16_initialize_a_javascript_module/templates/snippets/package_item.html :language: django .. seealso:: `Using data-* attributes `_ on the Mozilla Developer Network. If you now restart the development server and open http://127.0.0.1:5000/dataset in your web browser, you should see an extra info button next to each dataset shown. If you open a |javascript| console in your browser, you should see the message that your module has printed out. .. seealso:: Most web browsers come with built-in developer tools including a |javascript| console that lets you see text printed by |javascript| code to ``console.log()``, a |javascript| debugger, and more. For example: * `Firefox Developer Tools `_ * `Firebug `_ * `Chrome DevTools `_ If you have more than one dataset on your page, you'll see the module's message printed once for each dataset. The ``package_item.html`` template snippet is rendered once for each dataset that's shown in the list, so your ``