JavaScript
##########

.. toctree::
   :maxdepth: 2

As of Elgg 1.9, we encourage all developers to adopt the `AMD (Asynchronous Module
Definition) <http://requirejs.org/docs/whyamd.html>`_ standard for writing JavaScript code in Elgg.
The 1.8 version is still functional and is :ref:`described below<1.8-js>`.

AMD
===

Defining and loading a module in Elgg 1.9 takes two steps:

1. Define your module as asynchronous JavaScript.
2. Tell Elgg to asynchronously execute your module in the current page.

1. Define your module as asynchronous JavaScript
------------------------------------------------

You can define a module by creating a view or registering a URL.

Defining modules as a view
^^^^^^^^^^^^^^^^^^^^^^^^^^

Modules defined by creating views are immediately available for use and require no registration.
To register a module named ``my/module``, create the view ``views/default/js/my/module.js``.

.. warning: The extension must be ``.js``.

A basic module could look like this:

.. code-block:: javascript

	define(function(require) {
		var elgg = require("elgg");
		var $ = require("jquery");

		return function() {
			// Some logic in here
		};
	});

Define your module via a URL
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

You can define an existing AMD module using ``elgg_define_js()``. Traditional (browser-globals)
JavaScript files can also be defined as AMD modules if you shim them by setting ``exports`` and
optionally ``deps``.

.. warning:: Calls to ``elgg_define_js()`` must be in an ``init, system`` event handler.

.. code-block:: php

    <?php

	elgg_register_event_handler('init', 'system', 'amd_init');

	function amd_init() {
		// AMD module as the view js/backbone
		elgg_define_js('backbone');

		// AMD module with a different path
		elgg_define_js('backbone', array(
			'src' => '/vendors/backbone/backbone.js',
		));

		// Shimmed AMD module
		elgg_define_js('jquery.form', array(
			'src' => '/vendors/jquery/jquery.form.js',
			'deps' => array('jquery'),
			'exports' => 'jQuery.fn.ajaxForm',
		));
	}

Some things to note
^^^^^^^^^^^^^^^^^^^

1. Do not use ``elgg.provide()`` or ``elgg.require()`` anymore. They are fully replaced by
``define()`` and ``require()`` respectively.
2. Return the value of the module instead of adding to a global variable.
3. Static views (.css, .js) are automatically minified and cached by Elgg's simplecache system.


2. Tell Elgg to asynchronously execute your module in the current page
----------------------------------------------------------------------
Once an AMD module is defined, you can use ``require(["my/module"])`` from JavaScript to
access its "exported" value.

Also, calling ``elgg_require_js("my/module")`` from PHP tells Elgg to execute the module code
on the current page.


Migrating JS from Elgg 1.8 to AMD / 1.9
=======================================
**Current 1.8 JavaScript modules will continue to work with Elgg**.

We do not anticipate any backwards compatibility issues with this new direction and will fix any
issues that do come up. The old system will still be functional in Elgg 1.9, but developers are
encouraged to begin looking to AMD as the future of JS in Elgg.

.. _1.8-js:

Traditional JavaScript (1.8)
============================


Register third-party libraries with ``elgg_register_js``:

.. code:: php

   elgg_register_js('jquery', $cdnjs_url);

This will override any URLs previously registered under this name.

Load a library on the current page with ``elgg_load_js``:

.. code:: php

   elgg_load_js('jquery');

This will include and execute the linked code.

.. tip::

   Using inline scripts is strongly discouraged because:
    * They are not testable (maintainability)
    * They are not cacheable (performance)
    * Doing so forces some scripts to be loaded in ``<head>`` (performance)

   Inline scripts in core or bundled plugins are considered legacy bugs.

Core functions available in JS
==============================

``elgg.echo``

Translate interface text

.. code:: js

   elgg.echo('example:text', ['arg1']);


``elgg.system_message(message)``

Display a status message to the user.

.. code:: js

   elgg.system_message(elgg.echo('success'));
   

``elgg.register_error(message)``

Display an error message to the user.

.. code:: js

   elgg.register_error(elgg.echo('error'));


``elgg.forward()``

``elgg.normalize_url()``

Normalize a URL relative to the elgg root:

.. code:: js

   elgg.normalize_url('/blog'); // “http://localhost/elgg/blog”


Redirect to a new page.

.. code:: js

   elgg.forward('/blog');

This function automatically normalizes the URL.


``elgg.parse_url()``

Parse a URL into its component parts:

.. code:: js

   // returns an object with the properties
   // fragment: "fragment"
   // host: "community.elgg.org"
   // path: "/file.php"
   // query: "arg=val"
   elgg.parse_url(
     'http://community.elgg.org/file.php?arg=val#fragment');


``elgg.get_page_owner_guid()``

Get the GUID of the current page's owner.


``elgg.security.refreshToken()``

Force a refresh of all XSRF tokens on the page.

This is automatically called every 5 minutes by default.

This requires a valid security token in 1.8, but not in 1.9.

The user will be warned if their session has expired.


``elgg.security.addToken()``

Add a security token to an object, URL, or query string:

.. code:: js

   // returns an object:
   // __elgg_token: "1468dc44c5b437f34423e2d55acfdd87"
   // __elgg_ts: 1328143779
   // other: "data"
   elgg.security.addToken({'other': 'data'});
 
   // returns: "action/add?__elgg_ts=1328144079&__elgg_token=55fd9c2d7f5075d11e722358afd5fde2"
   elgg.security.addToken("action/add");
 
   // returns "?arg=val&__elgg_ts=1328144079&__elgg_token=55fd9c2d7f5075d11e722358afd5fde2"
   elgg.security.addToken("?arg=val");


``elgg.get_logged_in_user_entity()``

Returns the logged in user as an JS ElggUser object.


``elgg.get_logged_in_user_guid()``

Returns the logged in user's guid.


``elgg.is_logged_in()``

True if the user is logged in.


``elgg.is_admin_logged_in()``

True if the user is logged in and is an admin.


``elgg.config.get_language()``

Get the current page's language.


There are a number of configuration values set in the elgg object:

.. code:: js

   elgg.config.wwwroot; // The root of the website.
   elgg.config.language; // The default site language.
   elgg.config.viewtype; // The current page's viewtype
   elgg.config.version; // The Elgg version (YYYYMMDDXX).
   elgg.config.release; // The Elgg release (X.Y.Z).