{"id":13992008,"url":"https://github.com/tabalinas/jsgrid","last_synced_at":"2025-05-14T12:08:58.408Z","repository":{"id":22375093,"uuid":"25711561","full_name":"tabalinas/jsgrid","owner":"tabalinas","description":"Lightweight Grid jQuery Plugin","archived":false,"fork":false,"pushed_at":"2023-04-04T00:37:46.000Z","size":2558,"stargazers_count":1524,"open_issues_count":376,"forks_count":347,"subscribers_count":78,"default_branch":"master","last_synced_at":"2025-04-11T04:57:31.697Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://js-grid.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/tabalinas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2014-10-24T22:43:46.000Z","updated_at":"2025-03-20T06:43:20.000Z","dependencies_parsed_at":"2023-09-27T03:37:43.339Z","dependency_job_id":null,"html_url":"https://github.com/tabalinas/jsgrid","commit_stats":{"total_commits":400,"total_committers":35,"mean_commits":"11.428571428571429","dds":"0.14249999999999996","last_synced_commit":"bf0c991fc63f378329af24ce41cad29e12b74a88"},"previous_names":[],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabalinas%2Fjsgrid","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabalinas%2Fjsgrid/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabalinas%2Fjsgrid/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/tabalinas%2Fjsgrid/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/tabalinas","download_url":"https://codeload.github.com/tabalinas/jsgrid/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248345273,"owners_count":21088244,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-09T14:01:44.172Z","updated_at":"2025-04-11T04:57:36.699Z","avatar_url":"https://github.com/tabalinas.png","language":"JavaScript","funding_links":[],"categories":["JavaScript","Animation"],"sub_categories":["Tables"],"readme":"# jsGrid Lightweight Grid jQuery Plugin\n\n[![Build Status](https://travis-ci.org/tabalinas/jsgrid.svg?branch=master)](https://travis-ci.org/tabalinas/jsgrid)\n\nProject site [js-grid.com](http://js-grid.com/)\n\n**jsGrid** is a lightweight client-side data grid control based on jQuery.\nIt supports basic grid operations like inserting, filtering, editing, deleting, paging, sorting, and validating.\njsGrid is tunable and allows to customize appearance and components.\n\n![jsGrid lightweight client-side data grid](http://content.screencast.com/users/tabalinas/folders/Jing/media/beada891-57fc-41f3-ad77-fbacecd01d15/00000002.png)\n\n## Table of contents\n\n* [Demos](#demos)\n* [Installation](#installation)\n* [Basic Usage](#basic-usage)\n* [Configuration](#configuration)\n* [Grid Fields](#grid-fields)\n* [Methods](#methods)\n* [Callbacks](#callbacks)\n* [Grid Controller](#grid-controller)\n* [Validation](#validation)\n* [Localization](#localization)\n* [Sorting Strategies](#sorting-strategies)\n* [Load Strategies](#load-strategies)\n* [Load Indication](#load-indication)\n* [Requirement](#requirement)\n* [Compatibility](#compatibility)\n\n\n## Demos\n\nSee [Demos](http://js-grid.com/demos/) on project site.\n\nSample projects showing how to use jsGrid with the most popular backend technologies\n\n* **PHP** - https://github.com/tabalinas/jsgrid-php\n* **ASP.NET WebAPI** - https://github.com/tabalinas/jsgrid-webapi\n* **Express (NodeJS)** - https://github.com/tabalinas/jsgrid-express\n* **Ruby on Rail** - https://github.com/tabalinas/jsgrid-rails\n* **Django (Python)** - https://github.com/tabalinas/jsgrid-django\n\n\n## Installation\n\nInstall jsgrid with bower:\n\n```bash\n\n$ bower install js-grid --save\n\n```\n\nFind jsGrid cdn links [here](https://cdnjs.com/libraries/jsgrid). \n\n\n## Basic Usage\n\nEnsure that jQuery library of version 1.8.3 or later is included.\n\nInclude `jsgrid.min.js`, `jsgrid-theme.min.css`, and `jsgrid.min.css` files into the web page.\n\nCreate grid applying jQuery plugin `jsGrid` with grid config as follows:\n\n```javascript\n\n$(\"#jsGrid\").jsGrid({\n    width: \"100%\",\n    height: \"400px\",\n\n    filtering: true,\n    editing: true,\n    sorting: true,\n    paging: true,\n\n    data: db.clients,\n\n    fields: [\n        { name: \"Name\", type: \"text\", width: 150 },\n        { name: \"Age\", type: \"number\", width: 50 },\n        { name: \"Address\", type: \"text\", width: 200 },\n        { name: \"Country\", type: \"select\", items: db.countries, valueField: \"Id\", textField: \"Name\" },\n        { name: \"Married\", type: \"checkbox\", title: \"Is Married\", sorting: false },\n        { type: \"control\" }\n    ]\n});\n\n```\n\n\n## Configuration\n\nThe config object may contain following options (default values are specified below):\n\n```javascript\n\n{\n    fields: [],\n    data: [],\n\n    autoload: false,\n    controller: {\n        loadData: $.noop,\n        insertItem: $.noop,\n        updateItem: $.noop,\n        deleteItem: $.noop\n    },\n\n    width: \"auto\",\n    height: \"auto\",\n\n    heading: true,\n    filtering: false,\n    inserting: false,\n    editing: false,\n    selecting: true,\n    sorting: false,\n    paging: false,\n    pageLoading: false,\n\n    insertRowLocation: \"bottom\",\n    \n    rowClass: function(item, itemIndex) { ... },\n    rowClick: function(args) { ... },\n    rowDoubleClick: function(args) { ... },\n\n    noDataContent: \"Not found\",\n\n    confirmDeleting: true,\n    deleteConfirm: \"Are you sure?\",\n\n    pagerContainer: null,\n    pageIndex: 1,\n    pageSize: 20,\n    pageButtonCount: 15,\n    pagerFormat: \"Pages: {first} {prev} {pages} {next} {last} \u0026nbsp;\u0026nbsp; {pageIndex} of {pageCount}\",\n    pagePrevText: \"Prev\",\n    pageNextText: \"Next\",\n    pageFirstText: \"First\",\n    pageLastText: \"Last\",\n    pageNavigatorNextText: \"...\",\n    pageNavigatorPrevText: \"...\",\n\n    invalidNotify: function(args) { ... }\n    invalidMessage: \"Invalid data entered!\",\n    \n    loadIndication: true,\n    loadIndicationDelay: 500,\n    loadMessage: \"Please, wait...\",\n    loadShading: true,\n    loadIndicator: function(config) { ... }\n    loadStrategy: function(config) { ... }\n\n    updateOnResize: true,\n\n    rowRenderer: null,\n    headerRowRenderer: null,\n    filterRowRenderer: null,\n    insertRowRenderer: null,\n    editRowRenderer: null,\n    pagerRenderer: null\n}\n\n```\n\n### fields\nAn array of fields (columns) of the grid.\n\nEach field has general options and specific options depending on field type.\n\nGeneral options peculiar to all field types:\n\n```javascript\n\n{\n    type: \"\",\n    name: \"\",\n    title: \"\",\n    align: \"\",\n    width: 100,\n    visible: true,\n\n    css: \"\",\n\theadercss: \"\",\n    filtercss: \"\",\n    insertcss: \"\",\n    editcss: \"\",\n    \n    filtering: true,\n    inserting: true,\n    editing: true,\n    sorting: true,\n    sorter: \"string\",\n\n    headerTemplate: function() { ... },\n    itemTemplate: function(value, item) { ... },\n    filterTemplate: function() { ... },\n    insertTemplate: function() { ... },\n    editTemplate: function(value, item) { ... },\n\n    filterValue: function() { ... },\n    insertValue: function() { ... },\n    editValue: function() { ... },\n\n    cellRenderer: null,\n    \n    validate: null\n}\n\n```\n\n- **type** is a string key of field (`\"text\"|\"number\"|\"checkbox\"|\"select\"|\"textarea\"|\"control\"`) in fields registry `jsGrid.fields` (the registry can be easily extended with custom field types).\n- **name** is a property of data item associated with the column.\n- **title** is a text to be displayed in the header of the column. If `title` is not specified, the `name` will be used instead.\n- **align** is alignment of text in the cell. Accepts following values `\"left\"|\"center\"|\"right\"`.\n- **width** is a width of the column.\n- **visible** is a boolean specifying whether to show a column or not. (version added: 1.3)\n- **css** is a string representing css classes to be attached to the table cell.\n- **headercss** is a string representing css classes to be attached to the table header cell. If not specified, then **css** is attached instead.\n- **filtercss** is a string representing css classes to be attached to the table filter row cell. If not specified, then **css** is attached instead.\n- **insertcss** is a string representing css classes to be attached to the table insert row cell. If not specified, then **css** is attached instead.\n- **editcss** is a string representing css classes to be attached to the table edit row cell. If not specified, then **css** is attached instead.\n- **filtering** is a boolean specifying whether or not column has filtering (`filterTemplate()` is rendered and `filterValue()` is included in load filter object).\n- **inserting** is a boolean specifying whether or not column has inserting (`insertTemplate()` is rendered and `insertValue()` is included in inserting item).\n- **editing** is a boolean specifying whether or not column has editing (`editTemplate()` is rendered and `editValue()` is included in editing item).\n- **sorting** is a boolean specifying whether or not column has sorting ability.\n- **sorter** is a string or a function specifying how to sort item by the field. The string is a key of sorting strategy in the registry `jsGrid.sortStrategies` (the registry can be easily extended with custom sorting functions). Sorting function has the signature `function(value1, value2) { return -1|0|1; }`.\n- **headerTemplate** is a function to create column header content. It should return markup as string, DomNode or jQueryElement.\n- **itemTemplate** is a function to create cell content. It should return markup as string, DomNode or jQueryElement. The function signature is `function(value, item)`, where `value` is a value of column property of data item, and `item` is a row data item.\n- **filterTemplate** is a function to create filter row cell content. It should return markup as string, DomNode or jQueryElement.\n- **insertTemplate** is a function to create insert row cell content. It should return markup as string, DomNode or jQueryElement.\n- **editTemplate** is a function to create cell content of editing row. It should return markup as string, DomNode or jQueryElement. The function signature is `function(value, item)`, where `value` is a value of column property of data item, and `item` is a row data item.\n- **filterValue** is a function returning the value of filter property associated with the column.\n- **insertValue** is a function returning the value of inserting item property associated with the column.\n- **editValue** is a function returning the value of editing item property associated with the column.\n- **cellRenderer** is a function to customize cell rendering. The function signature is `function(value, item)`, where `value` is a value of column property of data item, and `item` is a row data item. The function should return markup as a string, jQueryElement or DomNode representing table cell `td`.\n- **validate** is a string as validate rule name or validation function or a validation configuration object or an array of validation configuration objects. Read more details about validation in the [Validation section](#validation). \n\nSpecific field options depends on concrete field type.\nRead about build-in fields in [Grid Fields](#grid-fields) section.\n\n### data\nAn array of items to be displayed in the grid. The option should be used to provide static data. Use the `controller` option to provide non static data.\n\n### autoload (default `false`)\nA boolean value specifying whether `controller.loadData` will be called when grid is rendered.\n\n### controller\nAn object or function returning an object with the following structure:\n\n```javascript\n\n{\n    loadData: $.noop,\n    insertItem: $.noop,\n    updateItem: $.noop,\n    deleteItem: $.noop\n}\n\n```\n\n- **loadData** is a function returning an array of data or jQuery promise that will be resolved with an array of data (when `pageLoading` is `true` instead of object the structure `{ data: [items], itemsCount: [total items count] }` should be returned). Accepts filter parameter including current filter options and paging parameters when `pageLoading` is `true`.\n- **insertItem** is a function returning inserted item or jQuery promise that will be resolved with inserted item. Accepts inserting item object.\n- **updateItem** is a function returning updated item or jQuery promise that will be resolved with updated item. Accepts updating item object.\n- **deleteItem** is a function deleting item. Returns jQuery promise that will be resolved when deletion is completed. Accepts deleting item object.\n\nRead more about controller interface in [Grid Controller](#grid-controller) section.\n\n### width (default: `\"auto\"`)\nSpecifies the overall width of the grid.\nAccepts all value types accepting by `jQuery.width`.\n\n### height (default: `\"auto\"`)\nSpecifies the overall height of the grid including the pager.\nAccepts all value types accepting by `jQuery.height`.\n\n### heading (default: `true`)\nA boolean value specifies whether to show grid header or not.\n\n### filtering (default: `false`)\nA boolean value specifies whether to show filter row or not.\n\n### inserting (default: `false`)\nA boolean value specifies whether to show inserting row or not.\n\n### editing (default: `false`)\nA boolean value specifies whether editing is allowed.\n\n### selecting (default: `true`)\nA boolean value specifies whether to highlight grid rows on hover.\n\n### sorting (default: `false`)\nA boolean value specifies whether sorting is allowed.\n\n### paging (default: `false`)\nA boolean value specifies whether data is displayed by pages.\n\n### pageLoading (default: `false`)\nA boolean value specifies whether to load data by page.\nWhen `pageLoading` is `true` the `loadData` method of controller accepts `filter` parameter with two additional properties `pageSize` and `pageIndex`.     \n\n### insertRowLocation (default: `\"bottom\"`)    \nSpecifies the location of an inserted row within the grid.    \nWhen `insertRowLocation` is `\"bottom\"` the new row will appear at the bottom of the grid. When set to `\"top\"`, the new row will appear at the top. \n\n### rowClass\nA string or a function specifying row css classes.\nA string contains classes separated with spaces.\nA function has signature `function(item, itemIndex)`. It accepts the data item and index of the item. It should returns a string containing classes separated with spaces.\n\n### rowClick\nA function handling row click. Accepts single argument with following structure:\n\n```javascript\n\n{\n     item       // data item\n     itemIndex  // data item index\n     event      // jQuery event\n}\n\n```\n\nBy default `rowClick` performs row editing when `editing` is `true`.\n\n### rowDoubleClick\nA function handling row double click. Accepts single argument with the following structure:\n\n```javascript\n\n{\n     item       // data item\n     itemIndex  // data item index\n     event      // jQuery event\n}\n\n```\n\n### noDataContent (default `\"Not found\"`)\nA string or a function returning a markup, jQueryElement or DomNode specifying the content to be displayed when `data` is an empty array.\n\n### confirmDeleting (default `true`)\nA boolean value specifying whether to ask user to confirm item deletion.\n\n### deleteConfirm (default `\"Are you sure?\"`)\nA string or a function returning string specifying delete confirmation message to be displayed to the user.\nA function has the signature `function(item)` and accepts item to be deleted.\n\n### pagerContainer (default `null`)\nA jQueryElement or DomNode to specify where to render a pager. Used for external pager rendering. When it is equal to `null`, the pager is rendered at the bottom of the grid.\n\n### pageIndex (default `1`)\nAn integer value specifying current page index. Applied only when `paging` is `true`.\n\n### pageSize (default `20`)\nAn integer value specifying the amount of items on the page. Applied only when `paging` is `true`.\n\n### pageButtonCount (default `15`)\nAn integer value specifying the maximum amount of page buttons to be displayed in the pager.\n\n### pagerFormat\nA string specifying pager format.\nThe default value is  `\"Pages: {first} {prev} {pages} {next} {last} \u0026nbsp;\u0026nbsp; {pageIndex} of {pageCount}\"`\n\nThere are placeholders that can be used in the format:\n\n```javascript\n\n{first}     // link to first page\n{prev}      // link to previous page\n{pages}     // page links\n{next}      // link to next page\n{last}      // link to last page\n{pageIndex} // current page index\n{pageCount} // total amount of pages\n{itemCount} // total amount of items\n\n```\n\n### pageNextText (default `\"Next\"`)\nA string specifying the text of the link to the next page.\n\n### pagePrevText (default `\"Prev\"`)\nA string specifying the text of the link to the previous page.\n\n### pageFirstText (default `\"First\"`)\nA string specifying the text of the link to the first page.\n\n### pageLastText (default `\"Last\"`)\nA string specifying the text of the link to the last page.\n\n### pageNavigatorNextText (default `\"...\"`)\nA string specifying the text of the link to move to next set of page links, when total amount of pages more than `pageButtonCount`.\n\n### pageNavigatorPrevText (default `\"...\"`)\nA string specifying the text of the link to move to previous set of page links, when total amount of pages more than `pageButtonCount`.\n\n### invalidMessage (default `\"Invalid data entered!\"`)\nA string specifying the text of the alert message, when invalid data was entered.\n\n### invalidNotify\nA function triggered, when invalid data was entered.\nBy default all violated validators messages are alerted.\nThe behavior can be customized by providing custom function.\n\nThe function accepts a single argument with the following structure:\n\n```javascript\n\n{\n    item                // inserting/editing item\n    itemIndex           // inserting/editing item index\n    errors              // array of validation violations in format { field: \"fieldName\", message: \"validator message\" }\n}\n\n```\n\nIn the following example error messages are printed in the console instead of alerting:\n\n```javascript\n    \n$(\"#grid\").jsGrid({\n    ...\n    \n    invalidNotify: function(args) {\n        var messages = $.map(args.errors, function(error) {\n            return error.field + \": \" + error.message;\n        });\n        \n        console.log(messages);\n    }\n    \n    ...\n}); \n    \n```\n\n### loadIndication (default `true`)\nA boolean value specifying whether to show loading indication during controller operations execution.\n\n### loadIndicationDelay (default `500`)\nAn integer value specifying the delay in ms before showing load indication. Applied only when `loadIndication` is `true`.\n\n### loadMessage (default `\"Please, wait...\"`)\nA string specifying the text of loading indication panel. Applied only when `loadIndication` is `true`.\n\n### loadShading (default `true`)\nA boolean value specifying whether to show overlay (shader) over grid content during loading indication. Applied only when `loadIndication` is `true`.\n\n### loadIndicator\nAn object or a function returning an object representing grid load indicator. Load indicator could be any js object supporting two methods `show` and `hide`.\n`show` is called on each loading start. `hide` method is called on each loading finish. Read more about custom load indicator in the [Load Indication](#load-indication) section.\n\n### loadStrategy\nAn object or a function returning an object representing grid load strategy. Load strategy defines behavior of the grid after loading data (any interaction with grid controller methods including data manipulation like inserting, updating and removing).\nThere are two build-in load strategies: `DirectLoadingStrategy` and `PageLoadingStrategy`. Load strategy depends on `pageLoading` option value.\nFor advanced scenarios custom load strategy can be provided. Read more about custom load strategies in the [Load Strategies](#load-strategies) section.\n\n### updateOnResize (default `true`)\nA boolean value specifying whether to refresh grid on window resize event.\n\n### rowRenderer (default `null`)\nA function to customize row rendering. The function signature is `function(item, itemIndex)`, where `item` is row data item, and `itemIndex` is the item index.\nThe function should return markup as a string, jQueryElement or DomNode representing table row `tr`.\n\n### headerRowRenderer (default `null`)\nA function to customize grid header row.\nThe function should return markup as a string, jQueryElement or DomNode representing table row `tr`.\n\n### filterRowRenderer (default `null`)\nA function to customize grid filter row.\nThe function should return markup as a string, jQueryElement or DomNode representing table row `tr`.\n\n### insertRowRenderer (default `null`)\nA function to customize grid inserting row.\nThe function should return markup as a string, jQueryElement or DomNode representing table row `tr`.\n\n### editRowRenderer (default `null`)\nA function to customize editing row rendering. The function signature is `function(item, itemIndex)`, where `item` is row data item, and `itemIndex` is the item index.\nThe function should return markup as a string, jQueryElement or DomNode representing table row `tr`.\n\n### pagerRenderer (default `null`)\n\u003e version added: 1.2 \n\nA function to customize pager rendering. The function accepts a single argument with the following structure:\n\n```javascript\n{\n    pageIndex,      // index of the currently opened page\n    pageCount       // total amount of grid pages \n} \n```\n\nThe function should return markup as a string, jQueryElement or DomNode representing the pager.\nIf `pagerRenderer` is specified, then `pagerFormat` option will be ignored.\n\n\n## Grid Fields\n\nAll fields supporting by grid are stored in `jsGrid.fields` object, where key is a type of the field and the value is the field class.\n\n`jsGrid.fields` contains following build-in fields:\n\n```javascript\n\n{\n    text: { ... },      // simple text input\n    number: { ... },    // number input\n    select: { ... },    // select control\n    checkbox: { ... },  // checkbox input\n    textarea: { ... },  // textarea control (renders textarea for inserting and editing and text input for filtering)\n    control: { ... }    // control field with delete and editing buttons for data rows, search and add buttons for filter and inserting row\n}\n\n```\n\nEach build-in field can be easily customized with general configuration properties described in [fields](#fields) section and custom field-specific properties described below.\n\n### text\nText field renders `\u003cinput type=\"text\"\u003e` in filter, inserting and editing rows.\n\nCustom properties:\n\n```javascript\n\n{\n    autosearch: true,   // triggers searching when the user presses `enter` key in the filter input\n    readOnly: false     // a boolean defines whether input is readonly (added in v1.4)\n}\n\n```\n\n### number\nNumber field renders `\u003cinput type=\"number\"\u003e` in filter, inserting and editing rows.\n\nCustom properties:\n\n```javascript\n\n{\n    sorter: \"number\",   // uses sorter for numbers\n    align: \"right\",     // right text alignment\n    readOnly: false     // a boolean defines whether input is readonly (added in v1.4)\n}\n\n```\n\n### select\nSelect field renders `\u003cselect\u003e` control in filter, inserting and editing rows.\n\nCustom properties:\n\n```javascript\n\n{\n    align: \"center\",            // center text alignment\n    autosearch: true,           // triggers searching when the user changes the selected item in the filter\n    items: [],                  // an array of items for select\n    valueField: \"\",             // name of property of item to be used as value\n    textField: \"\",              // name of property of item to be used as displaying value\n    selectedIndex: -1,          // index of selected item by default\n    valueType: \"number|string\", // the data type of the value\n    readOnly: false             // a boolean defines whether select is readonly (added in v1.4)\n}\n\n```\n\nIf valueField is not defined, then the item index is used instead.\nIf textField is not defined, then item itself is used to display value.\n\nFor instance the simple select field config may look like:\n\n```javascript\n\n{\n    name: \"Country\",\n    type: \"select\",\n    items: [ \"\", \"United States\", \"Canada\", \"United Kingdom\" ]\n}\n\n```\n\nor more complex with items as objects:\n\n```javascript\n\n{\n    name: \"Country\",\n    type: \"select\"\n    items: [\n         { Name: \"\", Id: 0 },\n         { Name: \"United States\", Id: 1 },\n         { Name: \"Canada\", Id: 2 },\n         { Name: \"United Kingdom\", Id: 3 }\n    ],\n    valueField: \"Id\",\n    textField: \"Name\"\n}\n\n```\n\n`valueType` defines whether the field value should be converted to a number or returned as a string. \nThe value of the option is determined automatically depending on the data type of `valueField` of the first item, but it can be overridden.\n\n### checkbox\nCheckbox field renders `\u003cinput type=\"checkbox\"\u003e` in filter, inserting and editing rows.\nFilter checkbox supports intermediate state for, so click switches between 3 states (checked|intermediate|unchecked).\n\nCustom properties:\n\n```javascript\n\n{\n    sorter: \"number\",   // uses sorter for numbers\n    align: \"center\",    // center text alignment\n    autosearch: true    // triggers searching when the user clicks checkbox in filter\n}\n\n```\n\n### textarea\nTextarea field renders `\u003ctextarea\u003e` in inserting and editing rows and `\u003cinput type=\"text\"\u003e` in filter row.\n\nCustom properties:\n\n```javascript\n\n{\n    autosearch: true,   // triggers searching when the user presses `enter` key in the filter input\n    readOnly: false     // a boolean defines whether textarea is readonly (added in v1.4)\n}\n\n```\n\n### control\nControl field renders delete and editing buttons in data row, search and add buttons in filter and inserting row accordingly.\nIt also renders button switching between filtering and searching in header row.\n\nCustom properties:\n\n```javascript\n\n{\n    editButton: true,                               // show edit button\n    deleteButton: true,                             // show delete button\n    clearFilterButton: true,                        // show clear filter button\n    modeSwitchButton: true,                         // show switching filtering/inserting button\n\n    align: \"center\",                                // center content alignment\n    width: 50,                                      // default column width is 50px\n    filtering: false,                               // disable filtering for column\n    inserting: false,                               // disable inserting for column\n    editing: false,                                 // disable editing for column\n    sorting: false,                                 // disable sorting for column\n\n    searchModeButtonTooltip: \"Switch to searching\", // tooltip of switching filtering/inserting button in inserting mode\n    insertModeButtonTooltip: \"Switch to inserting\", // tooltip of switching filtering/inserting button in filtering mode\n    editButtonTooltip: \"Edit\",                      // tooltip of edit item button\n    deleteButtonTooltip: \"Delete\",                  // tooltip of delete item button\n    searchButtonTooltip: \"Search\",                  // tooltip of search button\n    clearFilterButtonTooltip: \"Clear filter\",       // tooltip of clear filter button\n    insertButtonTooltip: \"Insert\",                  // tooltip of insert button\n    updateButtonTooltip: \"Update\",                  // tooltip of update item button\n    cancelEditButtonTooltip: \"Cancel edit\",         // tooltip of cancel editing button\n}\n\n```\n\n### Custom Field\n\nIf you need a completely custom field, the object `jsGrid.fields` can be easily extended.\n\nIn this example we define new grid field `date`:\n\n```javascript\n\nvar MyDateField = function(config) {\n    jsGrid.Field.call(this, config);\n};\n\nMyDateField.prototype = new jsGrid.Field({\n\n    css: \"date-field\",            // redefine general property 'css'\n    align: \"center\",              // redefine general property 'align'\n\n    myCustomProperty: \"foo\",      // custom property\n\n    sorter: function(date1, date2) {\n        return new Date(date1) - new Date(date2);\n    },\n\n    itemTemplate: function(value) {\n        return new Date(value).toDateString();\n    },\n\n    insertTemplate: function(value) {\n        return this._insertPicker = $(\"\u003cinput\u003e\").datepicker({ defaultDate: new Date() });\n    },\n\n    editTemplate: function(value) {\n        return this._editPicker = $(\"\u003cinput\u003e\").datepicker().datepicker(\"setDate\", new Date(value));\n    },\n\n    insertValue: function() {\n        return this._insertPicker.datepicker(\"getDate\").toISOString();\n    },\n\n    editValue: function() {\n        return this._editPicker.datepicker(\"getDate\").toISOString();\n    }\n});\n\njsGrid.fields.date = MyDateField;\n\n```\n\nTo have all general grid field properties custom field class should inherit `jsGrid.Field` class or any other field class.\nHere `itemTemplate` just returns the string representation of a date.\n`insertTemplate` and `editTemplate` create jQuery UI datePicker for inserting and editing row.\nOf course jquery ui library should be included to make it work.\n`insertValue` and `editValue` return date to insert and update items accordingly.\nWe also defined date specific sorter.\n\nNow, our new field `date` can be used in the grid config as follows:\n\n```javascript\n\n{\n    fields: [\n      ...\n      { type: \"date\", myCustomProperty: \"bar\" },\n      ...\n    ]\n}\n\n```\n\n\n## Methods\n\njsGrid methods could be called with `jsGrid` jQuery plugin or directly.\n\nTo use jsGrid plugin to call a method, just call `jsGrid` with method name and required parameters as next arguments:\n\n```javascript\n\n// calling method with jQuery plugin\n$(\"#grid\").jsGrid(\"methodName\", param1, param2);\n\n```\n\nTo call method directly you need to retrieve grid instance or just create grid with the constructor:\n\n```javascript\n\n// retrieve grid instance from element data\nvar grid = $(\"#grid\").data(\"JSGrid\");\n\n// create grid with the constructor\nvar grid = new jsGrid.Grid($(\"#grid\"), { ... });\n\n// call method directly\ngrid.methodName(param1, param2); \n\n```\n\n### cancelEdit()\nCancels row editing. \n\n```javascript\n\n$(\"#grid\").jsGrid(\"cancelEdit\");\n\n```\n\n### clearFilter(): `Promise`\nClears current filter and performs search with empty filter.\nReturns jQuery promise resolved when data filtering is completed. \n\n```javascript\n\n$(\"#grid\").jsGrid(\"clearFilter\").done(function() {\n    console.log(\"filtering completed\");\n});\n\n```\n\n### clearInsert()\nClears current inserting row. \n\n```javascript\n\n$(\"#grid\").jsGrid(\"clearInsert\");\n\n```\n\n### deleteItem(item|$row|rowNode): `Promise`\nRemoves specified row from the grid.\nReturns jQuery promise resolved when deletion is completed.\n\n**item|$row|rowNode** is the reference to the item or the row jQueryElement or the row DomNode.\n\n```javascript\n\n// delete row by item reference\n$(\"#grid\").jsGrid(\"deleteItem\", item);\n\n// delete row by jQueryElement\n$(\"#grid\").jsGrid(\"deleteItem\", $(\".specific-row\"));\n\n// delete row by DomNode\n$(\"#grid\").jsGrid(\"deleteItem\", rowNode);\n\n```\n\n### destroy()\nDestroys the grid and brings the Node to its original state.\n\n```javascript\n\n$(\"#grid\").jsGrid(\"destroy\");\n\n```\n\n### editItem(item|$row|rowNode)\nSets grid editing row.\n\n**item|$row|rowNode** is the reference to the item or the row jQueryElement or the row DomNode.\n\n```javascript\n\n// edit row by item reference\n$(\"#grid\").jsGrid(\"editItem\", item);\n\n// edit row by jQueryElement\n$(\"#grid\").jsGrid(\"editItem\", $(\".specific-row\"));\n\n// edit row by DomNode\n$(\"#grid\").jsGrid(\"editItem\", rowNode);\n\n```\n\n### getFilter(): `Object`\nGet grid filter as a plain object.\n\n```javascript\n\nvar filter = $(\"#grid\").jsGrid(\"getFilter\");\n\n```\n\n### getSorting(): `Object`\n\u003e version added: 1.2\n\nGet grid current sorting params as a plain object with the following format:\n\n```javascript\n\n{  \n    field,      // the name of the field by which grid is sorted\n    order       // 'asc' or 'desc' depending on sort order\n}\n\n```\n\n```javascript\n\nvar sorting = $(\"#grid\").jsGrid(\"getSorting\");\n\n```\n\n### fieldOption(fieldName|fieldIndex, optionName, [optionValue])\n\u003e version added: 1.3\n\nGets or sets the value of a field option.\n \n**fieldName|fieldIndex** is the name or the index of the field to get/set the option value (if the grid contains more than one field with the same name, the first field will be used).\n \n**optionName** is the name of the field option.\n\n**optionValue** is the new option value to set. \n\nIf `optionValue` is not specified, then the value of the field option `optionName` will be returned.\n\n```javascript\n\n// hide the field \"ClientName\"\n$(\"#grid\").jsGrid(\"fieldOption\", \"ClientName\", \"visible\", false);\n\n// get width of the 2nd field\nvar secondFieldOption = $(\"#grid\").jsGrid(\"fieldOption\", 1, \"width\");\n\n```\n\n### insertItem([item]): `Promise`\nInserts row into the grid based on item.\nReturns jQuery promise resolved when insertion is completed. \n \n**item** is the item to pass to `controller.insertItem`. \n\nIf `item` is not specified the data from inserting row will be inserted.\n\n```javascript\n\n// insert item from inserting row\n$(\"#grid\").jsGrid(\"insertItem\");\n\n// insert item\n$(\"#grid\").jsGrid(\"insertItem\", { Name: \"John\", Age: 25, Country: 2 }).done(function() {\n    console.log(\"insertion completed\");\n});\n\n```\n\n### loadData([filter]): `Promise`\nLoads data calling corresponding `controller.loadData` method. \nReturns jQuery promise resolved when data loading is completed.\nIt preserves current sorting and paging unlike the `search` method .\n \n**filter** is a filter to pass to `controller.loadData`. \n\nIf `filter` is not specified the current filter (filtering row values) will be applied.\n\n```javascript\n\n// load data with current grid filter\n$(\"#grid\").jsGrid(\"loadData\");\n\n// loadData with custom filter\n$(\"#grid\").jsGrid(\"loadData\", { Name: \"John\" }).done(function() {\n    console.log(\"data loaded\");\n});\n\n```\n\n### exportData([options])    \nTransforms the grid data into the specified output type.    \nOutput can be formatted, filtered or modified by providing options.     \nCurrently only supports CSV output.    \n\n```javascript\n//Basic export\nvar csv = $(\"#grid\").jsGrid(\"exportData\");\n\n//Full Options\nvar csv = $(\"#grid\").jsGrid(\"exportData\", {\n    type: \"csv\", //Only CSV supported\n    subset: \"all\" | \"visible\", //Visible will only output the currently displayed page\n    delimiter: \"|\", //If using csv, the character to seperate fields\n    includeHeaders: true, //Include header row in output\n    encapsulate: true, //Surround each field with qoutation marks; needed for some systems\n    newline: \"\\r\\n\", //Newline character to use\n    \n    //Takes each item and returns true if it should be included in output.\n    //Executed only on the records within the given subset above.\n    filter: function(item){return true},\n    \n    //Transformations are a way to modify the display value of the output.\n    //Provide a key of the field name, and a function that takes the current value.\n    transformations: {\n        \"Married\": function(value){\n            if (value === true){\n                return \"Yes\"\n            }\n            else{\n                return \"No\"\n            }\n        }\n    }\n});\n\n```\n\n### openPage(pageIndex)\nOpens the page of specified index.\n\n**pageIndex** is one-based index of the page to open. The value should be in range from 1 to [total amount of pages].\n\n\n### option(optionName, [optionValue])\nGets or sets the value of an option.\n \n**optionName** is the name of the option.\n\n**optionValue** is the new option value to set. \n\nIf `optionValue` is not specified, then the value of the option `optionName` will be returned.\n\n```javascript\n\n// turn off paging\n$(\"#grid\").jsGrid(\"option\", \"paging\", false);\n\n// get current page index\nvar pageIndex = $(\"#grid\").jsGrid(\"option\", \"pageIndex\");\n\n```\n\n### refresh()\nRefreshes the grid. Renders the grid body and pager content, recalculates sizes.\n\n```javascript\n\n$(\"#grid\").jsGrid(\"refresh\");\n\n```\n\n### render(): `Promise`\nPerforms complete grid rendering. If option `autoload` is `true` calls `controller.loadData`. The state of the grid like current page and sorting is retained. \nReturns jQuery promise resolved when data loading is completed. If auto-loading is disabled the promise is instantly resolved.   \n\n```javascript\n\n$(\"#grid\").jsGrid(\"render\").done(function() {\n    console.log(\"rendering completed and data loaded\");\n});\n\n```\n\n### reset()\nResets the state of the grid. Goes to the first data page, resets sorting, and then calls `refresh`.  \n\n```javascript\n\n$(\"#grid\").jsGrid(\"reset\");\n\n```\n\n### rowByItem(item): `jQueryElement`\n\u003e version added: 1.3\n\nGets the row jQuery element corresponding to the item.\n \n**item** is the item corresponding to the row.\n\n```javascript\n\nvar $row = $(\"#grid\").jsGrid(\"rowByItem\", item);\n\n```\n\n### search([filter]): `Promise`\nPerforms filtering of the grid.\nReturns jQuery promise resolved when data loading is completed.\nIt resets current sorting and paging unlike the `loadData` method.\n \n**filter** is a filter to pass to `controller.loadData`. \n\nIf `filter` is not specified the current filter (filtering row values) will be applied.\n\n```javascript\n\n// search with current grid filter\n$(\"#grid\").jsGrid(\"search\");\n\n// search with custom filter\n$(\"#grid\").jsGrid(\"search\", { Name: \"John\" }).done(function() {\n    console.log(\"filtering completed\");\n});\n\n```\n\n### showPrevPages()\nShows previous set of pages, when total amount of pages more than `pageButtonCount`.\n\n```javascript\n\n$(\"#grid\").jsGrid(\"showPrevPages\");\n\n```\n\n### showNextPages()\nShows next set of pages, when total amount of pages more than `pageButtonCount`.\n\n```javascript\n\n$(\"#grid\").jsGrid(\"showNextPages\");\n\n```\n\n### sort(sortConfig|field, [order]): `Promise`\nSorts grid by specified field.\nReturns jQuery promise resolved when sorting is completed.\n\n**sortConfig** is the plain object of the following structure `{ field: (fieldIndex|fieldName|field), order: (\"asc\"|\"desc\") }`\n\n**field** is the field to sort by. It could be zero-based field index or field name or field reference\n\n**order** is the sorting order. Accepts the following values: \"asc\"|\"desc\"\n\nIf `order` is not specified, then data is sorted in the reversed to current order, when grid is already sorted by the same field. Or `\"asc\"` for sorting by another field.\n\nWhen grid data is loaded by pages (`pageLoading` is `true`) sorting calls `controller.loadData` with sorting parameters. Read more in [Grid Controller](#grid-controller) section.\n\n```javascript\n\n// sorting grid by first field\n$(\"#grid\").jsGrid(\"sort\", 0);\n\n// sorting grid by field \"Name\" in descending order\n$(\"#grid\").jsGrid(\"sort\", { field: \"Name\", order: \"desc\" });\n\n// sorting grid by myField in ascending order \n$(\"#grid\").jsGrid(\"sort\", myField, \"asc\").done(function() {\n    console.log(\"sorting completed\");\n});\n\n```\n\n### updateItem([item|$row|rowNode], [editedItem]): `Promise`\nUpdates item and row of the grid.\nReturns jQuery promise resolved when update is completed.\n \n**item|$row|rowNode** is the reference to the item or the row jQueryElement or the row DomNode.\n\n**editedItem** is the changed item to pass to `controller.updateItem`.\n\nIf `item|$row|rowNode` is not specified then editing row will be updated.\n\nIf `editedItem` is not specified the data from editing row will be taken.\n\n```javascript\n\n// update currently editing row\n$(\"#grid\").jsGrid(\"updateItem\");\n\n// update currently editing row with specified data\n$(\"#grid\").jsGrid(\"updateItem\", { ID: 1, Name: \"John\", Age: 25, Country: 2 });\n\n// update specified item with particular data (row DomNode or row jQueryElement can be used instead of item reference)\n$(\"#grid\").jsGrid(\"updateItem\", item, { ID: 1, Name: \"John\", Age: 25, Country: 2 }).done(function() {\n    console.log(\"update completed\");\n});\n\n```\n\n### jsGrid.locale(localeName|localeConfig)\n\u003e version added: 1.4\n\nSet current locale of all grids.\n\n**localeName|localeConfig** is the name of the supported locale (see [available locales](src/i18n)) or a custom localization config. \nFind more information on custom localization config in [Localization](#localization). \n\n```javascript\n\n// set French locale\njsGrid.locale(\"fr\");\n\n```\n\n### jsGrid.setDefaults(config)\nSet default options for all grids.\n\n```javascript\n\njsGrid.setDefaults({\n    filtering: true,\n    inserting: true\n});\n\n```\n\n### jsGrid.setDefaults(fieldName, config)\nSet default options of the particular field.\n\n```javascript\n\njsGrid.setDefaults(\"text\", {\n    width: 150,\n    css: \"text-field-cls\"\n});\n\n```\n\n\n## Callbacks\n\njsGrid allows to specify a callback function to be executed on a particular event.\n\nThe following callbacks are supported:\n\n```javascript\n\n{\n    onDataLoading: function(args) {},    // before controller.loadData\n    onDataLoaded: function(args) {},     // on done of controller.loadData\n    onDataExporting: function() {},      // before data export\n    \n    onInit: function(args) {},           // after grid initialization \n    \n    onItemInserting: function(args) {},  // before controller.insertItem\n    onItemInserted: function(args) {},   // on done of controller.insertItem\n    onItemUpdating: function(args) {},   // before controller.updateItem\n    onItemUpdated: function(args) {},    // on done of controller.updateItem\n    onItemDeleting: function(args) {},   // before controller.deleteItem\n    onItemDeleted: function(args) {},    // on done of controller.deleteItem\n    onItemInvalid: function(args) {},    // after item validation, in case data is invalid\n    \n    onError: function(args) {},          // on fail of any controller call\n    \n    onOptionChanging: function(args) {}, // before changing the grid option\n    onOptionChanged: function(args) {},  // after changing the grid option\n    \n    onPageChanged: function(args) {},    // after changing the current page\n    \n    onRefreshing: function(args) {},     // before grid refresh\n    onRefreshed: function(args) {},      // after grid refresh\n}\n\n```\n\n### onDataLoading\nFires before data loading.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    filter              // loading filter object\n}\n\n```\n\n#### Cancel Data Loading \n\u003e version added: 1.2\n\nTo cancel data loading set `args.cancel = true`.\n\nIn the following example loading is canceled when the filter has empty 'name' field:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onDataLoading: function(args) {\n        // cancel loading data if 'name' is empty\n        if(args.filter.name === \"\") {\n            args.cancel = true;\n        }\n    }\n});\n\n```\n\n### onDataLoaded\nFires after data loading.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    data                // load result (array of items or data structure for loading by page scenario) \n}\n\n```\n\nIn the following example the loaded data is written to the browser console.\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onDataLoaded: function(args) {\n        console.log(args.data);\n    }\n});\n\n```\n\n### onInit\n\u003e version added: 1.5\n\nFires after grid initialization right before rendering. Usually used to get grid instance. \n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n}\n\n```\n\nIn the following example we get the grid instance on initialization:\n\n```javascript\n\nvar gridInstance;\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onInit: function(args) {\n        gridInstance = args.grid;\n    }\n});\n\n```\n\n### onError\nFires when controller handler promise failed.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    args                // an array of arguments provided to fail promise handler \n}\n\n```\n\n### onItemDeleting\nFires before item deletion.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    row                 // deleting row jQuery element\n    item                // deleting item\n    itemIndex           // deleting item index\n}\n\n```\n\n#### Cancel Item Deletion \n\u003e version added: 1.2\n\nTo cancel item deletion set `args.cancel = true`. This allows to do a validation before performing the actual deletion.\n\nIn the following example the deletion of items marked as `protected` is canceled:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onItemDeleting: function(args) {\n        // cancel deletion of the item with 'protected' field\n        if(args.item.protected) {\n            args.cancel = true;\n        }\n    }\n});\n\n```\n\n### onItemDeleted\nFires after item deletion.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    row                 // deleted row jQuery element\n    item                // deleted item\n    itemIndex           // deleted item index\n}\n\n```\n\n\n### onItemEditing\n\u003e version added: 1.4\n\nFires before item editing.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    row                 // editing row jQuery element\n    item                // editing item\n    itemIndex           // editing item index\n}\n\n```\n\n#### Cancel Item Editing \nTo cancel item editing set `args.cancel = true`. This allows to prevent row from editing conditionally.\n\nIn the following example the editing of the row for item with 'ID' = 0 is canceled:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onItemEditing: function(args) {\n        // cancel editing of the row of item with field 'ID' = 0 \n        if(args.item.ID === 0) {\n            args.cancel = true;\n        }\n    }\n});\n\n```\n\n\n### onItemInserting\nFires before item insertion.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    item                // inserting item\n}\n\n```\n\n#### Cancel Item Insertion \n\u003e version added: 1.2\n\nTo cancel item insertion set `args.cancel = true`. This allows to do a validation before performing the actual insertion.\n\nIn the following example insertion of items with the 'name' specified is allowed:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onItemInserting: function(args) {\n        // cancel insertion of the item with empty 'name' field\n        if(args.item.name === \"\") {\n            args.cancel = true;\n            alert(\"Specify the name of the item!\");\n        }\n    }\n});\n\n```\n\n### onItemInserted\nFires after item insertion.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    item                // inserted item\n}\n\n```\n\n### onItemInvalid\nFired when item is not following validation rules on inserting or updating.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    row                 // inserting/editing row jQuery element\n    item                // inserting/editing item\n    itemIndex           // inserting/editing item index\n    errors              // array of validation violations in format { field: \"fieldName\", message: \"validator message\" }\n}\n\n```\n\nThe following handler prints errors on the console\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onItemInvalid: function(args) {\n        // prints [{ field: \"Name\", message: \"Enter client name\" }]\n        console.log(args.errors);\n    }\n});\n\n```\n\n### onItemUpdating\nFires before item update.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    row                 // updating row jQuery element\n    item                // updating item\n    itemIndex           // updating item index\n    previousItem        // shallow copy (not deep copy) of item before editing\n}\n\n```\n\n#### Cancel Item Update \n\u003e version added: 1.2\n\nTo cancel item update set `args.cancel = true`. This allows to do a validation before performing the actual update.\n\nIn the following example update of items with the 'name' specified is allowed:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onItemUpdating: function(args) {\n        // cancel update of the item with empty 'name' field\n        if(args.item.name === \"\") {\n            args.cancel = true;\n            alert(\"Specify the name of the item!\");\n        }\n    }\n});\n\n```\n\n### onItemUpdated\nFires after item update.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    row                 // updated row jQuery element\n    item                // updated item\n    itemIndex           // updated item index\n    previousItem        // shallow copy (not deep copy) of item before editing\n}\n\n```\n\n### onOptionChanging\nFires before grid option value change.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    option              // name of option to be changed\n    oldValue            // old value of option\n    newValue            // new value of option\n}\n\n```\n\n### onOptionChanged\nFires after grid option value change.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    option              // name of changed option\n    value               // changed option value\n}\n\n```\n\n### onPageChanged\n\u003e version added: 1.5\n\nFires once grid current page index is changed. It happens either by switching between the pages with the pager links, or by calling the method `openPage`, or changing the option `pageIndex`.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n    pageIndex           // current page index\n}\n\n```\n\nIn the following example we print the current page index in the browser console once it has been changed:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    onPageChanged: function(args) {\n        console.log(args.pageIndex);\n    }\n});\n\n```\n\n### onRefreshing\nFires before grid refresh.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n}\n\n```\n\n### onRefreshed\nFires after grid refresh.\n\nHas the following arguments:\n\n```javascript\n\n{\n    grid                // grid instance\n}\n\n```\n\n\n## Grid Controller\n\nThe controller is a gateway between grid and data storage. All data manipulations call accordant controller methods.\nBy default grid has an empty controller and can work with static array of items stored in option `data`.\n\nA controller should implement the following methods:\n\n```javascript\n\n{\n    loadData: function(filter) { ... },\n    insertItem: function(item) { ... },\n    updateItem: function(item) { ... },\n    deleteItem: function(item) { ... }\n}\n\n```\n\nAsynchronous controller methods should return a Promise, resolved once the request is completed. \nStarting v1.5 jsGrid supports standard JavaScript Promise/A, earlier versions support only jQuery.Promise.\n\nFor instance the controller for typical REST service might look like:\n\n```javascript\n\n{\n    loadData: function(filter) {\n        return $.ajax({\n            type: \"GET\",\n            url: \"/items\",\n            data: filter\n        });\n    },\n    \n    insertItem: function(item) {\n        return $.ajax({\n            type: \"POST\",\n            url: \"/items\",\n            data: item\n        });\n    },\n    \n    updateItem: function(item) {\n        return $.ajax({\n            type: \"PUT\",\n            url: \"/items\",\n            data: item\n        });\n    },\n    \n    deleteItem: function(item) {\n        return $.ajax({\n            type: \"DELETE\",\n            url: \"/items\",\n            data: item\n        });\n    },\n}\n\n```\n\n### loadData(filter): `Promise|dataResult`\nCalled on data loading.\n\n**filter** contains all filter parameters of fields with enabled filtering\n\nWhen `pageLoading` is `true` and data is loaded by page, `filter` includes two more parameters:\n\n```javascript\n\n{\n    pageIndex     // current page index\n    pageSize      // the size of page\n}\n\n```\n\nWhen grid sorting is enabled, `filter` includes two more parameters:\n\n```javascript\n\n{\n    sortField     // the name of sorting field\n    sortOrder     // the order of sorting as string \"asc\"|\"desc\"\n}\n\n```\n\nMethod should return `dataResult` or jQuery promise that will be resolved with `dataResult`.\n  \n**dataResult** depends on `pageLoading`. When `pageLoading` is `false` (by default), then data result is a plain javascript array of objects.\nIf `pageLoading` is `true` data result should have following structure \n\n```javascript\n\n{\n    data          // array of items\n    itemsCount    // total items amount in storage\n}\n\n```\n\n### insertItem(item): `Promise|insertedItem`\nCalled on item insertion.\n\nMethod should return `insertedItem` or jQuery promise that will be resolved with `insertedItem`. \nIf no item is returned, inserting item will be used as inserted item. \n\n**item** is the item to be inserted.\n\n### updateItem(item): `Promise|updatedItem`\nCalled on item update.\n\nMethod should return `updatedItem` or jQuery promise that will be resolved with `updatedItem`.\nIf no item is returned, updating item will be used as updated item.\n\n**item** is the item to be updated.\n\n### deleteItem(item): `Promise`\nCalled on item deletion.\n\nIf deletion is asynchronous, method should return jQuery promise that will be resolved when deletion is completed.\n\n**item** is the item to be deleted.\n\n## Validation\n\u003e version added: 1.4\n\n### Field Validation Config\n\n`validate` option of the field can have 4 different value types `string|Object|Array|function`:\n\n1. `validate: \"validatorName\"`\n\n**validatorName** - is a string key of the validator in the `jsGrid.validators` registry. The registry can be easily extended. See available [built-in validators here](#built-in-validators). \n\nIn the following example the `required` validator is applied:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    fields: [{ type: \"text\", name: \"FieldName\", validate: \"required\" }]\n});\n\n```\n\n2. `validate: validationConfig`\n\n**validateConfig** - is a plain object of the following structure:\n \n```javascript\n{\n    validator: string|function(value, item, param), // built-in validator name or custom validation function \n    message: string|function,                       // validation message or a function(value, item) returning validation message \n    param: any                                      // a plain object with parameters to be passed to validation function\n}\n```\n\nIn the following example the `range` validator is applied with custom validation message and range provided in parameters:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    fields: [{ \n        type: \"number\", \n        name: \"Age\", \n        validate: {\n            validator: \"range\",\n            message: function(value, item) {\n                return \"The client age should be between 21 and 80. Entered age is \\\"\" + value + \"\\\" is out of specified range.\";\n            },\n            param: [21, 80]\n        }\n    }]\n});\n\n```\n\n3. `validate: validateArray`\n\n**validateArray** - is an array of validators. It can contain \n\n * `string` - validator name\n * `Object` - validator configuration of structure `{ validator, message, param }`\n * `function` - validation function as `function(value, item)`\n\nIn the following example the field has three validators: `required`, `range`, and a custom function validator:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    fields: [{ \n        type: \"number\", \n        name: \"Age\", \n        validate: [\n            \"required\",\n            { validator: \"range\", param: [21, 80] },\n            function(value, item) {\n                return item.IsRetired ? value \u003e 55 : true; \n            }\n        ]\n    }]\n});\n\n```\n\n4. `validate: function(value, item, param)`\n\nThe parameters of the function:\n\n * `value` - entered value of the field\n * `item` - editing/inserting item\n * `param` - a parameter provided by validator (applicable only when validation config is defined at validation object or an array of objects)\n\nIn the following example the field has custom validation function:\n\n```javascript\n\n$(\"#grid\").jsGrid({\n    ...\n    \n    fields: [{ \n        type: \"text\", \n        name: \"Phone\", \n        validate: function(value, item) {\n            return value.length == 10 \u0026\u0026 phoneBelongsToCountry(value, item.Country); \n        }\n    }]\n});\n\n```\n\n### Built-in Validators\n\nThe `jsGrid.validators` object contains all built-in validators. The key of the hash is a validator name and the value is the validator config.\n\n`jsGrid.validators` contains the following build-in validators:\n\n * **required** - the field value is required\n * **rangeLength** - the length of the field value is limited by range (the range should be provided as an array in `param` field of validation config)\n * **minLength** - the minimum length of the field value is limited (the minimum value should be provided in `param` field of validation config)\n * **maxLength** - the maximum length of the field value is limited (the maximum value should be provided in `param` field of validation config)\n * **pattern** - the field value should match the defined pattern (the pattern should be provided as a regexp literal or string in `param` field of validation config)\n * **range** - the value of the number field is limited by range (the range should be provided as an array in `param` field of validation config)\n * **min** - the minimum value of the number field is limited (the minimum should be provided in `param` field of validation config)\n * **max** - the maximum value of the number field is limited (the maximum should be provided in `param` field of validation config)\n\n### Custom Validators\n\nTo define a custom validator just add it to the `jsGrid.validators` object.\n \nIn the following example a custom validator `time` is registered:\n\n```javascript\n\n    jsGrid.validators.time = {\n        message: \"Please enter a valid time, between 00:00 and 23:59\",\n        validator: function(value, item) {\n            return /^([01]\\d|2[0-3]|[0-9])(:[0-5]\\d){1,2}$/.test(value);\n        }\n    }\n    \n```\n\n\n## Localization\n\u003e version added: 1.4\n\nCurrent locale can be set for all grids on the page with the [`jsGrid.locale(localeName)`](#jsgridlocalelocalenamelocaleconfig) method.\n\nNew custom locale can be added to `jsGrid.locales` hash like the following:\n\n```javascript\n\njsGrid.locales.my_lang = {\n    // localization config goes here\n    ...\n};\n    \n```\n\nHere is how localization config looks like for Spanish [i18n/es.js](src/i18n/es.js).\n\nFind all available locales [here](src/i18n).\n\n\n## Sorting Strategies\n\nAll supported sorting strategies are stored in `jsGrid.sortStrategies` object, where key is a name of the strategy and the value is a `sortingFunction`.\n\n`jsGrid.sortStrategies` contains following build-in sorting strategies:\n\n```javascript\n\n{\n    string: { ... },          // string sorter\n    number: { ... },          // number sorter\n    date: { ... },            // date sorter\n    numberAsString: { ... }   // numbers are parsed before comparison\n}\n\n```\n\n**sortingFunction** is a sorting function with the following format:\n\n```javascript\n\nfunction(value1, value2) {\n    if(value1 \u003c value2) return -1; // return negative value when first is less than second\n    if(value1 === value2) return 0; // return zero if values are equal\n    if(value1 \u003e value2) return 1; // return positive value when first is greater than second\n}\n\n```\n\n### Custom Sorting Strategy\n\nIf you need a custom sorting strategy, the object `jsGrid.sortStrategies` can be easily extended.\n\nIn this example we define new sorting strategy for our client objects:\n\n```javascript\n\n// clients array\nvar clients = [{\n    Index: 1,\n    Name: \"John\",\n    Age: 25\n}, ...];\n\n// sort clients by name and then by age\njsGrid.sortStrategies.client = function(index1, index2) {\n    var client1 = clients[index1];\n    var client2 = clients[index2];\n    return client1.Name.localeCompare(client2.Name) \n        || client1.Age - client2.Age;\n};\n\n```\n\nNow, our new sorting strategy `client` can be used in the grid config as follows:\n\n```javascript\n\n{\n    fields: [\n      ...\n      { name: \"Index\", sorter: \"client\" },\n      ...\n    ]\n}\n\n```\n\nWorth to mention, that if you need particular sorting only once, you can just inline sorting function in `sorter` not registering the new strategy:\n\n```javascript\n{\n    fields: [\n      ...\n      { \n          name: \"Index\", \n          sorter: function(index1, index2) {\n              var client1 = clients[index1];\n              var client2 = clients[index2];\n              return client1.Name.localeCompare(client2.Name) \n                  || client1.Age - client2.Age;\n          }\n      },\n      ...\n    ]\n}\n```\n\n## Load Strategies\n\nThe behavior of the grid regarding data source interaction is defined by load strategy. \n\nThe load strategy has the following methods: \n\n```javascript\n{\n    firstDisplayIndex: function() {},                        // returns the index of the first displayed item\n    lastDisplayIndex: function() {},                         // returns the index of the last displayed item\n    itemsCount: function() {},                               // returns the total amount of grid items\n    \n    openPage: function(index) {},                            // handles opening of the particular page\n    loadParams: function() {},                               // returns additional parameters for controller.loadData method\n    sort: function() {},                                     // handles sorting of data in the grid, should return a Promise\n    reset: function() {},                                    // handles grid refresh on grid reset with 'reset' method call, should return a Promise\n    \n    finishLoad: function(loadedData) {},                     // handles the finish of loading data by controller.loadData\n    finishInsert: function(insertedItem) {},                 // handles the finish of inserting item by controller.insertItem\n    finishDelete: function(deletedItem, deletedItemIndex) {} // handles the finish of deleting item by controller.deleteItem\n}\n```\n\nThere are two build-in load strategies: DirectLoadingStrategy (for `pageLoading=false`) and PageLoadingStrategy (for `pageLoading=true`).\n\n### DirectLoadingStrategy\n\n**DirectLoadingStrategy** is used when loading by page is turned off (`pageLoading=false`).\n\nIt provides the following behavior:\n\n- **firstDisplayIndex** returns the index of the first item on the displayed page\n- **lastDisplayIndex** returns the index of the last item on the displayed page\n- **itemsCount** returns the actual amount of all the loaded items\n- **openPage** refreshes the grid to render items of current page\n- **loadParams** returns empty object, since no extra load params are needed\n- **sort** sorts data items and refreshes the grid calling `grid.refresh`\n- **reset** calls `grid.refresh` method to refresh the grid\n- **finishLoad** puts the data coming from `controller.loadData` into the option `data` of the grid \n- **finishInsert** pushes new inserted item into the option `data` and refreshes the grid\n- **finishDelete** removes deleted item from the option `data` and resets the grid\n\n### PageLoadingStrategy\n\n**PageLoadingStrategy** is used when data is loaded to the grid by pages (`pageLoading=true`).\n\nIt provides the following behavior:\n\n- **firstDisplayIndex** returns 0, because all loaded items displayed on the current page\n- **lastDisplayIndex** returns the amount of loaded items, since data loaded by page\n- **itemsCount** returns `itemsCount` provided by `controller.loadData` (read more in section [controller.loadData](#loaddatafilter-promisedataresult))\n- **openPage** calls `grid.loadData` to load data for the current page\n- **loadParams** returns an object with the structure `{ pageIndex, pageSize }` to provide server with paging info\n- **sort** calls `grid.loadData` to load sorted data from the server\n- **reset** calls `grid.loadData` method to refresh the data\n- **finishLoad** saves `itemsCount` returned by server and puts the `data` into the option `data` of the grid \n- **finishInsert** calls `grid.search` to reload the data\n- **finishDelete** calls `grid.search` to reload the data\n\n### Custom LoadStrategy\n\nThe option `loadStrategy` allows to specify a custom load strategy to customize the behavior of the grid.\nThe easiest way to do it is to inherit from existing strategy.\n\nBy default DirectLoadingStrategy resets the grid (resets the paging and sorting) when an item is deleted.\nThe following example shows how to create a custom strategy to avoid grid reset on deletion of an item.\n\n```javascript\nvar MyCustomDirectLoadStrategy = function(grid) {\n    jsGrid.loadStrategies.DirectLoadingStrategy.call(this, grid);\n};\n\nMyCustomDirectLoadStrategy.prototype = new jsGrid.loadStrategies.DirectLoadingStrategy();\n\nMyCustomDirectLoadStrategy.prototype.finishDelete = function(deletedItem, deletedItemIndex) {\n    var grid = this._grid;\n    grid.option(\"data\").splice(deletedItemIndex, 1);\n    grid.refresh();\n};\n\n// use custom strategy in grid config\n$(\"#grid\").jsGrid({\n    \n    loadStrategy: function() {\n        return new MyCustomDirectLoadStrategy(this);\n    },\n    \n    ...\n    \n}); \n\n```\n\n\n## Load Indication\n\nBy default jsGrid uses jsGrid.LoadIndicator. Load indicator can be customized with the `loadIndicator` option. \nSet an object or a function returning an object supporting the following interface:\n\n```javascript\n{\n    show: function() { ... } // called on loading start\n    hide: function() { ... } // called on loading finish\n}\n```\n\nThis simple example prints messages to console instead of showing load indicator:\n\n```javascript\n{\n    loadIndicator: {\n        show: function() { \n            console.log(\"loading started\");\n        },\n        hide: function() {\n            console.log(\"loading finished\"); \n        }\n    }\n}\n```\n\nIf `loadIndicator` is a function, it accepts the config of load indicator in the following format:\n\n```javascript\n{\n    container,  // grid container div\n    message,    // the loading message is a value of the option loadMessage\n    shading     // the boolean value defining whether to show shading. This is a value of the option loadShading\n}\n```\n\nThe similar example printing messages to console shows how to configure loading indicator with a function returning an object:\n\n```javascript\n{\n    loadIndicator: function(config) {\n        return {\n            show: function() { \n                console.log(\"loading started: \" + config.message);\n            },\n            hide: function() {\n                console.log(\"loading finished\"); \n            }\n        };\n    }\n}\n```\n\nCustomization of loading indicator is useful, when you want to use any external load indicator that is used for all other ajax requests on the page.\n\nThis example shows how to use [spin.js](http://fgnass.github.io/spin.js/) to indicate loading:\n\n```javascript\n{\n    loadIndicator: function(config) {\n        var container = config.container[0];\n        var spinner = new Spinner();\n    \n        return {\n            show: function() {\n                spinner.spin(container);\n            },\n            hide: function() {\n                spinner.stop();\n            }\n        };\n    }\n}\n```\n\n## Requirement\n\njQuery (1.8.3 or later)\n\n\n## Compatibility\n\n**Desktop**\n\n* Chrome\n* Safari\n* Firefox\n* Opera 15+\n* IE 8+\n\n**Mobile**\n\n* Safari for iOS\n* Chrome for Android\n* IE10 for WP8\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftabalinas%2Fjsgrid","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftabalinas%2Fjsgrid","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftabalinas%2Fjsgrid/lists"}