====
open
====

.. js:function:: open(options, callback, async)

**domain**: client 

**language**: javascript

**class** :doc:`Item class </refs/client/item_api>`

Description
===========

Call ``open`` to sends a request to the server for obtaining an item dataset. 

The ``open`` method can have the following parameters:

* ``options`` - an object that specifies the parameters of the request sent to 
  the server
* ``callback``: if the parameter is not present, the request is sent to the 
  server synchronously, otherwise, the request is executed asynchronously and 
  after the dataset is received, the callback is executed
* ``async``: if its value is true, and callback parameter is missing, the request 
  is executed asynchronously 
  
The order of parameters doesn't matter.

The method initializes the item 
:doc:`fields <at_fields>`,
formulates parameters of a request, based on the ``options`` and triggers the 
:doc:`on_before_open <on_before_open>` event 
handler if one is defined for the item.

After that it sends the request to the server. If ``callback`` 
parameter-function is specified, the request is executed asynchronously, 
otherwise - synchronouslly. 

The server, after recieving the request, checks if the corresponding item on the 
server (item of the 
:doc:`task tree </programming/task_tree>` 
with the same ID attribute) has the
:doc:`on_open </refs/server/item/on_open>`
event handler. If so it executes this event handler and returns the result of 
the execution to the client, otherwise generates a SELECT SQL query, based on 
parameters of the request, executes this query and returns the result to the client.

The client, after receiving the result of the request, changes its dataset and
sets :doc:`active <at_active>`
to true, the
:doc:`item_state <at_item_state>` 
to browse mode, goes to the first record of the dataset, triggers 
:doc:`on_after_open <on_after_open>` 
and 
:doc:`on_filters_applied <on_filters_applied>`
event handlers (if they are defined for the item), and updates controls.

Then it calls ``callback`` function if it was specified.

Options
-------

The ``options`` object parameter can have the following attributes:

* ``expanded`` - if the value of this attribute is true, the SELECT query, generated
  on the server, will have JOIN clauses to get lookup values of the 
  :doc:`lookup fields </programming/data/lookup_fields>`
  , otherwise no lookup values will be returned. The default value if ``true``.
  
* ``fields`` - use this parameter to specify the WHERE clause of the SELECT 
  query. This parameter is a list of field names. If it is omitted, the fields 
  defined by the
  :doc:`set_fields <m_set_fields>`
  method will be used. If the
  :doc:`set_fields <m_set_fields>`
  method was not called before the ``open`` method execution, all the fields 
  created by a developer will be used.

* ``where`` - use this parameter to specify how records will be filtered in the 
  SQL query. This parameter is an object of key-value pairs, where keys are
  field names, that are followed, after double underscore, by a filtering symbols
  (see
  :doc:`Filtering records </programming/data/filtering_records>`
  ). If this parameter is omitted, values
  defined by the
  :doc:`set_where <m_set_where>`
  method will be used. If the
  :doc:`set_where <m_set_where>`
  method was not called before the ``open`` method execution, and ``where`` 
  parameter is omitted, then the values of 
  :doc:`filters </programming/data/filters>` 
  defined for the item will be used to filter records.
  
* ``order_by`` - use ``order_by`` to specify sort order of the records. This 
  parameter is a list of field names. If there is a sign '-' before the field 
  name, then on this field records will be sorted in decreasing order. If this 
  parameter is omitted, a list defined by the   
  :doc:`set_order_by <m_set_order_by>`
  method will be used.

* ``offset`` -  use ``offset`` to specify the offset of the first row to return.

* ``limit`` - use ``limit`` to limit the output of a SQL query to the first 
  so-many rows.

* ``funcs`` - this parameter can be a an object of key-value pairs, where key is 
  a field name and value is function name that will be applied to the field in
  the SELECT Query

* ``group_by`` - use ``group_by`` to specify fields to group the result of the 
  query by. This parameter must be a list of field names.

* ``open_empty`` - if this parameter is set to ``true``, the application does 
  not send a request to the server but just initializes an empty dataset. 
  The default value  if ``false``.

* ``params`` - use the parameter to pass some user defined options to be used in
  the 
  :doc:`on_open </refs/server/item/on_open>`
  event handler on the server. This parameter must be an object of key-value pairs

.. note::
    When the 
    :doc:`paginate <at_paginate>`
    attribute of the item is set to ``true`` and a table is created by the
    :doc:`create_table <m_create_table>`
    method, the ``limit`` and ``offset``  parameters are set internally by the
    table depending on its row number and current page.

Examples
========

.. code-block:: js

    function get_customer_sales(task, customer_id) {
        var date1 = new Date(new Date().setYear(new Date().getFullYear() - 5)),
            date2 = new Date(),
            invoices = task.invoices.copy();
    
        invoices.open({
            fields: ['customer', 'invoicedate', 'total'], 
            where: {customer: customer_id, invoicedate__ge: date1, invoicedate__le: date2},
            order_by: ['invoicedate']
        });
    }

.. code-block:: js

    function get_customer_sales(task, customer_id) {
        var date1 = new Date(new Date().setYear(new Date().getFullYear() - 5)),
            date2 = new Date(),
            invoices = task.invoices.copy();
    
        invoices.set_fields(['customer', 'invoicedate', 'total']);
        invoices.set_where({customer: customer_id, invoicedate__ge: date1, invoicedate__le: date2});
        invoices.set_order_by(['invoicedate']);
        invoices.open();
    }

.. code-block:: js

    function get_sales(task) {
        var sales = task.invoices.copy();

        sales.open({
            fields: ['customer', 'id', 'total'], 
            funcs: {'id': 'count', 'total': 'sum'}, 
            group_by: ['customer'], 
            order_by: ['customer']
        });
    }
