arta.js

arta.js includes a JavaScript object with several methods to help building the front end of an Artaengine application. This tutorial shows how this functions work. arta.js requires jQuery.

Dumping variables

To inspect JavaScript variables use Arta.I():

var var1,
    var2 = [1, 2, 3],
    var3 = {a: 'A',b: 'B',c: 'C'},
    var4 = 5.6;

Arta.I(var1, var2, var3);

Message box

To show a message use Arta.msg('title', 'message'). The message contents are put inside a container with id msg-box. If container not exists the message will be shown in an alert. To change the id to something else: Arta.msgBox = 'my-custom-box';

/* open a dialog box width=height=400px */
Arta.msg('Title', 'Contents can include HTML');

/* open a dialog box with two custom buttons */
Arta.msg(
  'Title',
  'Contents can include HTML',
  {
    Close: function () { /* do something */ Arta.msgClose(); }
    OK:    function () { /* do something */ Arta.msgClose(); }
  }
);

Message box example:

<div id="msg-box"></div>

The message contents would be as:

<div id="msg-box" style="display: block;">
  <h2 id="msg-box-title">Title!</h2>
  <div id="msg-box-content">Contents can include HTML!</div>
  <div id="msg-box-buttons">
    <button onclick="...">Cancel</button>
    <button onclick="...">OK</button>
  </div>
</div>

To manually set the container id to a container:

<div id="my-msg-box"></div>
Arta.msgBox = 'my-msg-box';
Arta.msg('Title', 'Contents can include HTML');

To make the page to jump to message box top put Arta.msgJump = true; before showing the message.

Loading icon

To add a loading icon to the page add an invisible element to the page, the id attribute must be loading-icon:

<img id="loading-icon" src="mages/loading.gif" alt="Loading..."/>

Turn on and off as shown below:

Arta.loading();

/* do something */

Arta.loading(false);

Arta.ajax() employs this method to turn loading icon on and off.

On demand JS and CSS

To add CSS file(s) to a page use Arta.injectCSS:

/* add one file */
Arta.injectCSS('http://my-domain.com/styles/style.css');
/* add some files */
Arta.injectCSS([
    'http://my-domain.com/styles/style1.css',
    'http://my-domain.com/styles/style2.css',
    'http://my-domain.com/styles/style3.css'
]);

To add JavaScript file(s) to a page use Arta.injectJS:

/* add one file */
Arta.injectJS('http://my-domain.com/js/myjsfile.js');
/* add some files */
Arta.injectJS([
    'http://my-domain.com/js/myjsfile1.js',
    'http://my-domain.com/js/myjsfile2.js',
    'http://my-domain.com/js/myjsfile3.js'
]);

To do something after JavaScript file(s) have been completely loaded:

/* add one file */
Arta.injectJS(
  'http://my-domain.com/js/myjsfile.js',
  function () {
    alert('The JavaScript file is loaded');
  }
);
/* add some files */
Arta.injectJS(
  [
    'http://my-domain.com/js/myjsfile1.js',
    'http://my-domain.com/js/myjsfile2.js',
    'http://my-domain.com/js/myjsfile3.js'
  ],
  function () {
    alert('All JavaScript files have been loaded');
  }
);

To add CSS and JavaScript file(s) to a page use Arta.inject. All arguments are optional:

Arta.inject(
  ['http://my-domain.com/styles/style.css'],
  [
    'http://my-domain.com/js/myjsfile1.js',
    'http://my-domain.com/js/myjsfile2.js',
  ],
  function () {
    alert('All JavaScript files have been loaded');
  }
);

AJAX

To send AJAX requests to the server use the Arta.ajax() method:

// send ajax request to url
Arta.ajax(url);

Arta.ajax(url).success(function (res) { });

Arta.ajax(url)
    .success(function (res) {

    })
    .fail(function (jqXHR, textStatus, errorThrown) {

    });

// send data by an ajax post request to a url
var data = {'name': 'Mehdi', 'age': 10};

Arta.ajax(url, data);

Arta.ajax(url, data)
    .success(function (res) {

    });

Arta.ajax(url, data)
    .success(function (res) {

    })
    .fail(function (jqXHR, textStatus, errorThrown) {

    });

// send data by an ajax get request to a url
Arta.ajax(url, data, 'get');

Arta.ajax(url, data, 'get')
    .success(function (oJ) {

    });

Arta.ajax(url, data, 'get')
    .success(function (res) {

    })
    .fail(function (jqXHR, textStatus, errorThrown) {

    });

// set ajax jQuery params
Arta.ajax(url, data, 'get', {jQuery-ajax-params});

Arta.ajax(url, data, 'get', {jQuery-ajax-params})
    .success(function (res) { });

Arta.ajax(url, data, 'get', {jQuery-ajax-params})
    .success(function (res) {

    })
    .fail(function (jqXHR, textStatus, errorThrown) {

    });

// legacy
Arta.ajax(url, data, method, function (res) { /* success */ });

Arguments

  • Request URL. Can be a complete URL or a path to BASE_URL.
  • Data to be sent. A dictionary(JavaScript object) as {key: value,...}.
  • Can be set to post or get. Default is post.
  • A dictionary(JavaScript object) of jQuery ajax settings.

On success and fail

Optionally you can set callback functions for the ajax success and fail events. This callback functions are set to two methods chained with the ajax() method:

  • Function to be called on success. This function can have one argument which is the data responded by the server to the ajax request. By default this data is expected to be a dictionary(JavaScript object) in other words the server is supposed to send back a JSON response otherwise ajax() would consider something went wrong on the server. However you can change this behavior by setting Arta.ajaxOnlyObj = false which will consider any response to be correct. When Arta.ajaxOnlyObj = true which is the default, if the server response is not an object then the success call back function will not be called and if if the application is in debug mode (DEBUG = on) the response will be shown in a popup.
  • Function to be called on fail/error. This function can have three arguments which are jQuery ajax error function arguments jqXHR, textStatus, errorThrown. When application is in DEBUG mode, if the request fails and this callback function is not set then a message will popup to inform the developer.

Example

Arta.ajax(
        'ajax/Users/update',
        {active: 'Y', id: 5}
    )
    .success(function (res) {
        Arta.I('Dump oJ:', res);
    })
    .fail(function (jqXHR, textStatus, errorThrown) {
        Arta.I(jqXHR, textStatus, errorThrown);
    });

Controlling the behavior with properties

  • To make AJAX calls synchronous set this property to false.
  • To set AJAX request timeout set this property (milliseconds).
  • Number of request attempts when request timeouts. If an AJAX request fails because of timeout error then the request will be attempted as many times as set to this property before admiting there is an fail/error.
  • . When true if request fails a message will be shown to user. This message is defined in i18n.ajaxErrorMsg.
  • When true the response to the ajax request must be an object. If an object is not sent back and in DEBUG mode then a message will show the responded value to the developer. It is recommended that the server always responds back a JSON objects, this helps debugging while developing the application, because if an error happens on the server side then the error message is responded instead of the JSON object and the developer will immediately see it.
  • By default Arta.ajax will call Arta.loading(). To not to do so set this property to false.

Returned data conventions

When the server responds data as a JSON object, the data object can include some meaningful keys as listed and explained below upon this keys the Arta.ajax() will do stuff, it means you can control the DOM from the server:

  • To set contents of HTML elements by their ids set an array of ids and contents to a key named html inside the data sent back from the server.
  • To append contents of HTML elements by their ids set an array of ids and contents to a key named html-append, htmlAppend or htmlappend inside the data sent back from the server.
  • To prepend contents of HTML elements by their ids set an array of ids and contents to a key named html-prepend, htmlPrepend or htmlprepend inside the data sent back from the server.
  • To replace HTML elements by their ids set an array of ids and replace contents to a key named replace inside the data sent back from the server.
  • To change the value attribute of HTML elements by their ids set an array of ids and values to a key named vals inside the data sent back from the server.
  • To change attributes of HTML elements by their ids set an array of ids and attributes/values to a key named atts inside the data sent back from the server.
  • By default arta data structure is added to the return data when using Response.writeJson() in a factory. The CSS and JavaScript files set inside the factory will be included inside this data and will be loaded into page. BASE_URL and DEBUG mode will be defined as public for JavaScript (if not defined before the AJAX call). And any JavaScript code assigned by $this->jsx() inside the factory will be executed.

Example

Arta.ajax('ajax/Users/list').success(function (oJ) {
    Arta.I(oJ);
});

Assume the AJAX request above is responded by below factory:

class Users extends Response {
    public $js = array(
        'jquery',
        'jquery/ui',
    );
    public $css = array(
        'jquery/ui',
    );

    public function listUsers($request) {
        $this->js[]  = 'user/list';
        $this->jsx[] = 'alert("Hello");';

        /*  QUERY DATA HERE ...  */

        /* add data to be send */
        $this->count = $recordCount;
        $this->test  = array(1, 2, 3, 'a' => 'aaa', 'b' => 'bbb',);

        /* add meaningful data to change the front-end */
        $this->html = array(
            'list-container'         => $this->show('users/list.xhtml'),
            'paging-links-container' => $paging->render(),
        );
        $this->htmlPrepend = array(
            'list-container' => 'START OF THE LIST',
        );
        $this->htmlAppend = array(
            'list-container' => 'END OF THE LIST',
        );
        $this->replace = array(
            'bad' => 'This element was bad so it is replaced with this text',
        );
        $this->vals = array(
            'list-title' => _('Users list'),
        );
        $this->atts = array(
            'search-form-container' => array(
                'class' => 'hidden',
            ),
        );
        $this->jsx[] = 'alert("Hi there!");';

        /* send back data */
        $this->writeJson();
    }
}

While oJ is an object which contains all the data set in the factory and can be used inside the success function, the meaningful data will be applied to the DOM and the CSS/JavaScript files will be added to the page (if not already exist) then the JavaScript source codes will be executed.

To avoid dependency problems, the JavaScript files are loaded one by one in a queue, when all JavaScript files are leaded then the JavaScript source codes are executed.

AJAX file upload

To upload file(s) without refreshing the page use Arta.upload(). This method will upload a file as an AJAX request. The usage and behavior is almost identical to Arta.ajax().

HTML:

<input id="file1" type="file" accept="image/*"/>
<input id="file2" type="file" accept="image/*"/>
<button id="upload">Upload</button>

JavaScript:

// variable to store files
var files;
// add files event
$('input[type=file]').change(function (e) {
    files = e.target.files;
});

// upload the file
$('#upload').change(function (e) {

    // any of the below calls will upload the file(s)

    Arta.upload(url, files);

    Arta.upload(url, files)
        .success(function (res) {

        });

    Arta.upload(url, files)
        .success(function (res) {

        })
        .fail(function (jqXHR, textStatus, errorThrown) {

        });

    // to post data beside along the upload
    var data = {'name': 'Mehdi', 'age': 10};

    // send data by an ajax get request to a url
    Arta.upload(url, files, data);

    Arta.upload(url, files, data)
        .success(function (oJ) {

        });

    Arta.upload(url, files, data)
        .success(function (res) {

        })
        .fail(function (jqXHR, textStatus, errorThrown) {

        });

    // set ajax jQuery params
    Arta.upload(url, files, data, {jQuery-ajax-params});

    Arta.upload(url, files, data, {jQuery-ajax-params})
        .success(function (res) { });

    Arta.upload(url, files, data, {jQuery-ajax-params})
        .success(function (res) {

        })
        .fail(function (jqXHR, textStatus, errorThrown) {

        });
});

PHP

class Photos extends Response {

    public function uploadFiles($request) {
        // get data from post
        // $key = $request->Post->key;

        // get the Upload object
        $upload = $request->Upload;

        // debug view the uploaded files
        // I($request->Upload->getFiles());

        $errors = array();
        $success = array();

        // optional: to validate an upload you can put an of the rules
        $rules = array(
            // will return error if file is not uploaded
            'required' => true,
            'size'     => self::MAX_UPLOAD_SIZE,
            // can be array or string
            'type'     => array('image/jpeg', 'image/png'),
            'ext'      => array('jpg', 'jpeg', 'png'),
            // set an external method to manually validate
            'plugin'   => array($edit, 'isPhoto'),
            // or
            // 'plugin'   => 'PhotoEdit::isPhoto',
        );

        foreach ($upload->get() as $key => $uploaded) {
            $validate = $uploaded->validate($rules);
            if ($validate === true) {
                $baseFile = '/path/to/uploads/file.jpg';
                // save the uploaded file
                $uploaded->moveTo($baseFile);
            } else {
                // check UploadError class for error codes and messages
                $errors[$key] = $validate;
            }
        }

        // send back data to JavaScript as JSON
        $this->errors = $errors;
        $this->done = $success;
        $this->writeJson();
    }
}

Arguments

  • Request URL. Can be a complete URL or a path to BASE_URL.
  • Files to upload. A dictionary(JavaScript object) of file elements.
  • Data to be sent. A dictionary(JavaScript object) as {key: value,...}.
  • A dictionary(JavaScript object) of jQuery ajax settings.

On success and fail

Optionally you can set callback functions for the ajax success and fail events. This callback functions are set to two methods chained with the ajax() method:

  • Function to be called on success. This function can have one argument which is the data responded by the server to the ajax request. By default this data is expected to be a dictionary(JavaScript object) in other words the server is supposed to send back a JSON response otherwise ajax() would consider something went wrong on the server. However you can change this behavior by setting Arta.ajaxOnlyObj = false which will consider any response to be correct. When Arta.ajaxOnlyObj = true which is the default, if the server response is not an object then the success call back function will not be called and if if the application is in debug mode (DEBUG = on) the response will be shown in a popup.
  • Function to be called on fail/error. This function can have three arguments which are jQuery ajax error function arguments jqXHR, textStatus, errorThrown. When application is in DEBUG mode, if the request fails and this callback function is not set then a message will popup to inform the developer.

Controlling the behavior with properties

  • To make AJAX calls synchronous set this property to false.
  • To set AJAX request timeout set this property (milliseconds).
  • Number of request attempts when request timeouts. If an AJAX request fails because of timeout error then the request will be attempted as many times as set to this property before admiting there is an fail/error.
  • . When true if request fails a message will be shown to user. This message is defined in i18n.ajaxErrorMsg.
  • When true the response to the ajax request must be an object. If an object is not sent back and in DEBUG mode then a message will show the responded value to the developer. It is recommended that the server always responds back a JSON objects, this helps debugging while developing the application, because if an error happens on the server side then the error message is responded instead of the JSON object and the developer will immediately see it.
  • By default Arta.ajax will call Arta.loading(). To not to do so set this property to false.

Returned data conventions

When the server responds data as a JSON object, the data object can include some meaningful keys as listed and explained below upon this keys the Arta.ajax() will do stuff, it means you can control the DOM from the server:

  • To set contents of HTML elements by their ids set an array of ids and contents to a key named html inside the data sent back from the server.
  • To append contents of HTML elements by their ids set an array of ids and contents to a key named html-append, htmlAppend or htmlappend inside the data sent back from the server.
  • To prepend contents of HTML elements by their ids set an array of ids and contents to a key named html-prepend, htmlPrepend or htmlprepend inside the data sent back from the server.
  • To replace HTML elements by their ids set an array of ids and replace contents to a key named replace inside the data sent back from the server.
  • To change the value attribute of HTML elements by their ids set an array of ids and values to a key named vals inside the data sent back from the server.
  • To change attributes of HTML elements by their ids set an array of ids and attributes/values to a key named atts inside the data sent back from the server.
  • By default arta data structure is added to the return data when using Response.writeJson() in a factory. The CSS and JavaScript files set inside the factory will be included inside this data and will be loaded into page. BASE_URL and DEBUG mode will be defined as public for JavaScript (if not defined before the AJAX call). And any JavaScript code assigned by $this->jsx() inside the factory will be executed.

Validating forms

To validate a form created by Artaengine class Form use Arta.validate():

HTML:

<div id="user-form-container">
    <!-- THE FORM INPUTS AND SELECTS WILL BE HERE -->
</div>

JavaScript:

// get the form from PHP and load into the HTML
Arta.ajax('Users/getAddForm', {}, 'get');

$('#add-user-button').click(function () {
    var data = Arta.validate('#user-form-container');

    // if the emtered data was not valid 
    if (data === false) {
        // shows the validation error messages in the msg-box and returns false
        // this messages can be customized and localized
        return Arta.validateMsg();
    }

    // send the validated data to the server
    Arta.ajax('Users/add', data);

    return true;
});

PHP:

class users {

    public function getAddForm($request) {
        $form = new Form();
        $form
            ->add(new User(), 'username', 'password', 'email');
            ->button(_('Add user'), '', 'add-user-button');

        $this->html('user-form-container', $form->render());
        $this->writeJson();
    }

    public function add($request) {
        $model = new User();
        Form::bindTo($model);
        $this->ok = $mountain->add()->commit();
        $this->writeJson();
    }
}

A form is a set of inputs and widgets which interact with the user and doesn't have to be inside a form element.

Pass the value of the id attribute of an HTML element which contains the form to Arta.validate().

If the form is not validated Arta.validate() will return false, otherwise the validated data will be returned.

The returned validated data can be sent to the server and filled into a model to add or update data.

When data is not valid and false has been returned, Arta.validateMsg() can be used to show a message telling which data was not valid and why. Arta.validateMsg() uses Arta.msg() to show the messages. Messages can be customized and be locale aware. arta.js contains the deafult English messages. The /javascript/i18n/en.js is included in the Artaengine download package, it contains the translation keys, customize and replicate this file for your locales and load after loading arta.js to override the default messages. The translations:

Arta.i18n = {
    /* delete dialog */
    deleteMsg: 'The following items and data will be removed.',
    del: 'Delete',
    cancel: 'Cancel',
    /* ajax */
    ajaxDebugTitle: 'Debug/Error message (only shown in DEBUG mode)',
    ajaxErrorMsg: 'The last request could not be completed, please try again',
    /* form validation */
    validate: {
        title:     'Form data validation errors',
        required:  'is required',
        regex:     'invalid format',
        minLen:    'string length is too short',
        maxLen:    'string length is too long',
        maxNumber: 'is too large',
        minNumber: 'is too small',
        'int':     'must be an integer',
        'float':   'must be a floating point number',
        password:  'passwords do not matching',
        email:     'must be a valid email format',
        url:       'must be a valid URL format',
        ip:        'must be a valid IP format',
        time:      'must be a valid time format',
        date:      'must be a valid date format',
        datetime:  'must be a valid date-time format',

        /*  By default Artaengine JavaScript library form validator arta.validate()
            uses the labels defined in the above structure.
            To define specific messages for specific widgets for specific
            validation errors do as shown below: */
        x: {
            // by input/widget element id
            'my-widget-id': {
                // any of the keys from validate i.e:
                regex: 'enter valid data in my widget',
                required: 'my widget can not be empty'
            }
        }
    }
};

To validate a form with submit button (non AJAX) set the validating function to the form's onsubmit:

<form id="user-form-container" onsubmit="return addUSer();">

Binding posted data to a model is described in: Data modeling - input form .

Using Artaengine data models + form generators + validating and sending using arta.js makes the data entry work flow as robust, easy and automated as it can be. However you can use the JavaScript form validation for forms which are not created from models or by the form generator, just you have to mark the inputs and widgets with validation hints as the form generator does.

To perform a search on model data, based on a search form created by Artaengine class FormSearch use Arta.searchPack():

HTML:

<div id="user-form-container">
    <!-- THE FORM INPUTS AND SELECTS WILL BE HERE -->
</div>

JavaScript:

$('#search-user-button').click(function () {
    var searchPack = Arta.searchPack('#form');
    Arta.ajax('/Users/search', searchPack);
});

PHP:

class users {

    public function getSearchForm($request) {
        $form = new FormSearch('search');
        $form
            ->add(new User(), '#', 'username', 'password', 'email');
            ->button(_('Search'), '', 'search-user-button');

        $this->html('user-form-container', $form->render());
        $this->writeJson();
    }

    public function search($request) {
        $model = new User();

        $form = new FormSearch('search');
        $form->bind($model, 'post');

        $user->sort('id DESC')->query();

        // create the user list ...

        $this->writeJson();
    }
}

Pass the value of the id attribute of an HTML element which contains the form to Arta.searchPack().

Note that this is just a basic example, usually you would need to also do pagination and take care of the page indexes and sorting, etc.

Pass the #id attribute of an HTML element which contains the form to Arta.searchPack().

It is recommended to always send the search pack data via ajax and feed it to FormSearch, as handling the complex data manually would not be easy.

The data outputted by Arta.searchPack() must be sent to server as shown in the example. On server class FormSearch can perform a search on model as described in: Data modeling - search form .

Use the methods of Arta.Cookie to work with cookies:

// expires after browser is closed
Arta.Cookie.set('my-cookie-for-a-session', 'value');
// expires after 30 days
Arta.Cookie.set('my-cookie-for-a-month', 'value', 30);

// get cookie value
var valStr = Arta.Cookie.get('my-cookie');

// remove cookie
var valStr = Arta.Cookie.remove('my-cookie');

// cookie exists
if (Arta.Cookie.has('my-cookie')) {
    alert('It has it!');
}

// get all cookies (keys)
var keysAsList = Arta.Cookie.keys();
// debug var
Arta.I(keysAsList);

To jump to the page top or an element use Arta.jump():

// jump to the page top
Arta.jump();
// jump to 100px lower than the page top
Arta.jump(null, 100);

// jump to the element
Arta.jump('the-element-id');
// jump to 20px lower than the element
Arta.jump('the-element-id', 20);

var e = $('#the-element');
// jump to the element
Arta.jump(e);
// jump to 20px lower than the element
Arta.jump(e, 20);

Related examples

Model input forms

Model search forms

Model tables

TOP