diff --git a/CHANGELOG.md b/CHANGELOG.md index 88e7721cc30b9743dc3db07676d1e127b39ebd1c..e62308e44baefead580498999b21541f53431c84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,23 @@ # Change log +- `0.15.0`: + - [$.formhandler](docs/formhandler.md) now supports client-side validation + and sorting by multiple columns. A bug related to encoding special + characters is also fixed. + +- `0.14.0`: + - [$.formhandler](docs/formhandler.md) uses a `onhashchange: false` to + disable changing the URL when elements are selected. This is useful when + simply viewing tables and not drilling down. + - [$.formhandler](docs/formhandler.md) bugfixes: allows column names with + spaces. Clear all removes all filters. + - [$.urlfilter](docs/urlfilter.md) supports checkboxes, inputs and forms + (but has a few known bugs) + - Interactive documentation added for [$.template](docs/template.md) and + [$.urlfilter](docs/urlfilter.md) + - [$.urlchange](docs/urlchange.md) documents how to listen to multiple + changes, and when the hash is reset + - `0.13.1`: - Fixes a critical bug. Multiple g1 modules could not be loaded on the same page. diff --git a/README.md b/README.md index 91896c64c999a63a30e110cf11510d916573e301..8c436e19a6197b36dd28cdf05f0bf720ad41f5dd 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ To use all features, add this to your HTML: - [g1.url.parse](docs/url.md) parses a URL into a structured object - [url.join](docs/url.md#urljoin) joins two URLs - [url.update](docs/url.md#urlupdate) updates a URL's query parameters +- [g1.fuzzysearch](docs/fuzzysearch.md) searches for text with fuzzy matching - [$.ajaxchain](docs/ajaxchain.md) chains AJAX requests, loading multiple items in sequence - [L.TopoJSON](docs/topojson.md) loads TopoJSON files just like GeoJSON. Requires [topojson](https://github.com/topojson/topojson) - [$.dispatch](docs/dispatch.md) is like [trigger](https://api.jquery.com/trigger/) but sends a native event (triggers non-jQuery events too) @@ -72,14 +73,6 @@ For debugging, use [dist/g1.js](dist/g1.js) -- an un-minified version. [CHANGELOG](CHANGELOG.md) mentions all release changes. -Brief notes with examples are described in Gramex releases. For example: - -- [v0.12](https://learn.gramener.com/guide/release/1.49/#g1-animated-templates) -- [v0.11](https://learn.gramener.com/guide/release/1.47/#g1) -- [v0.10.1](https://learn.gramener.com/guide/release/1.45/#g1) -- [v0.10.0](https://learn.gramener.com/guide/release/1.44/#g1) -- [v0.9.0](https://learn.gramener.com/guide/release/1.41/#g1) - ## Browser support Every release is tested on the current versions of Chrome, Edge and Firefox. diff --git a/docs/dropdown.md b/docs/dropdown.md index 0a0e361432229dd7ff674522178251af6cd7197d..fd24d9fe0c8a6addad1c2e5e24331334938cb367 100644 --- a/docs/dropdown.md +++ b/docs/dropdown.md @@ -3,9 +3,14 @@ `$.dropdown()` creates dropdowns that integrate well with [$.urlfilter](#urlfilter) and [$.urlchange](#urlchange). -It requires the [bootstrap-select](https://silviomoreto.github.io/bootstrap-select/examples/) +It requires the [bootstrap-select](https://developer.snapappointments.com/bootstrap-select/) library and its dependencies. +```html + + +``` + Example: ```html diff --git a/docs/formhandler.md b/docs/formhandler.md index 65c0f08f93d36e838482eb80350a4684a160f8e3..c09c0b618687f0562d78523c4638ae1031cba836 100644 --- a/docs/formhandler.md +++ b/docs/formhandler.md @@ -30,75 +30,70 @@ The full list of options is below. Simple options can be specified as `data-` at - `title`: for header display. Defaults to the same value as `name` - `type`: `text` (default) / `number` / `date`. Data type. Determines filters to be used - `format`: string / function that returns formatted cell display value. - - function accepts an object with these keys: - - `name`: column name - - `value`: cell data value - - `row`: row data - - `index`: row index - - `data`: the dataset from `src` - - strings specify a numeral.js format if the value is a number (you must include numeral.js) - - strings specify a moment.js format if the value is a date (you must include moment.js) - - `editable`: `true` (default) / `false`. When `true`, edit and save buttons appears at end of each row. - - To bind UI input element such as dropdown, datepicker, radio etc., `editable` accepts an object with these keys. + - function accepts an object with these keys: + - `name`: column name + - `value`: cell data value + - `row`: row data + - `index`: row index + - `data`: the dataset from `src` + - strings specify a numeral.js format if the value is a number (you must include numeral.js) + - strings specify a moment.js format if the value is a date (you must include moment.js) + - `editable`: `true` (default) / `false`. When `true`, edit and save buttons appears at end of each row. To bind UI input element such as dropdown, datepicker, radio etc., `editable` accepts an object with these keys. - `input`: **Mandatory**. The type of input element to use. The valid values are checkbox, radio, range, select, and any other legal [HTML form input type](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input). - `options`: An array of options to select from. **Mandatory** if `input` is either of `select` or `radio` - - `attrs`: To place common attributes such as max, min, placeholder, name etc., on the `input` element. - - Example: - `input: 'number', attrs: {step: 10, placeholder: '0 - 1000', name: 'some_name'}` would render as - - `` - + - `attrs`: To place common attributes such as max, min, placeholder, name etc., on the input. + Example: `{placeholder: "Age", max:100}` renders `` + - `validationMessage`: The message to be shown when invalid input is entered. + Example: `"Age must be less than 100"` - `template`: string template / function that renders the cell. - - function accepts an object with these keys: - - `name`: column name - - `value`: cell data value - - `format`: formatted cell display value - - `link`: cell link value (if applicable) - - `index`: row index - - `row`: row data - - `data`: the dataset from `src` - - string template can use the above variables + - function accepts an object with these keys: + - `name`: column name + - `value`: cell data value + - `format`: formatted cell display value + - `link`: cell link value (if applicable) + - `index`: row index + - `row`: row data + - `data`: the dataset from `src` + - string template can use the above variables - `sort`: `true` / `false` / operators dict with: - - `{'': 'Sort ascending', '-': 'Sort descending'}` (default) + - `{'': 'Sort ascending', '-': 'Sort descending'}` (default) - `filters`: `true` (default) / `false` / operators dict with: - - `{'', 'Equals...', '!', 'Does not equal...', ...}`. - The default list of operators is based on the auto-detected type of the column. + - `{'', 'Equals...', '!', 'Does not equal...', ...}`. The default list of operators is based on the auto-detected type of the column. - `link`: string / function that generates a link for this each cell. - - If no `link:` is specified, clicking on the cell filters by that cell. - - If `link:` is a function, opens a new window with the URL as `fn(args)`. - - function accepts an object with these keys: - - `name`: column name - - `value`: cell data value - - `format`: formatted cell display value - - `index`: row index - - `row`: row data - - `data`: the dataset from `src` - Example: `function(args) { return 'https://example.org/city/' + args.value }` - - If `link:` is a string, opens a new window with the string URL interpolated as a lodash template with an object (mentioned above) as data. - Example: `"https://example.org/city/<%- value >"` + - If no `link:` is specified, clicking on the cell filters by that cell. + - If `link:` is a function, opens a new window with the URL as `fn(args)`. + - function accepts an object with these keys: + - `name`: column name + - `value`: cell data value + - `format`: formatted cell display value + - `index`: row index + - `row`: row data + - `data`: the dataset from `src` + - Example: `function(args) { return 'https://example.org/city/' + args.value }` + - If `link:` is a string, opens a new window with the string URL interpolated as a lodash template with an object (mentioned above) as data. + Example: `"https://example.org/city/<%- value >"` - `hideable`: `true` (default) / `false`. Show or hide `Hide` option in header dropdown - `hide`: `true` / `false` (default). Hides the column - `unique`: list of values. Adds a list of checkboxes of unique values to filter on, in the column header dropdown. - `edit`: Shows the Edit control. Can be `true` / `false` (default). Can also pass an object. - - `done`: function that gets called after saving the edited row. + - `done`: function that gets called after saving the edited row. - `add`: Show the Add control. Can be `true` / `false` (default). Can also pass an object. - - `done`: function that gets called after saving the new row. + - `done`: function that gets called after saving the new row. - `actions`: A list of objects. you need not add it to actions - - `{{action}}`: a function() that gets triggered on clicking the element with `data-action='{{action}}` attribute. The value of `data-action` attribute must match with key `{{action}}` in `actions`. - - function accepts an object with these keys: - - `row`: row data - - `index`: index of the row in the dataset from `src` - - `notify(message)`: a function that shows a notification - - If the return value can be a jQuery deferred (e.g. `$.ajax`), it shows a loading indicator and a success / failure message when the deferred is resolved. Example: - - `highlight_row`: `function(obj) { $(obj.row).addClass('.yellow_color')}`. Either a new column can be defined in `columns:` (example: {`name`: `Additional Col`}) with cell_template having an element with data attribute as `data-action='highlight_row'` or can use an existing column but with custom template that has an element with data attribute as `data-action='highlight_row'`. - - Note: DELETE operation is executed on a row if an element has data attribute `data-action='delete'`. If `delete` action is given in `actions`, the function given for `delete` is executed on click of an element with `data-action='delete'` instead od executing DELETE operation. + - `{{action}}`: a function() that gets triggered on clicking the element with `data-action='{{action}}` attribute. The value of `data-action` attribute must match with key `{{action}}` in `actions`. + - function accepts an object with these keys: + - `row`: row data + - `index`: index of the row in the dataset from `src` + - `notify(message)`: a function that shows a notification + - If the return value can be a jQuery deferred (e.g. `$.ajax`), it shows a loading indicator and a success / failure message when the deferred is resolved. Example: + - `highlight_row`: `function(obj) { $(obj.row).addClass('.yellow_color')}`. Either a new column can be defined in `columns:` (example: {`name`: `Additional Col`}) with cell_template having an element with data attribute as `data-action='highlight_row'` or can use an existing column but with custom template that has an element with data attribute as `data-action='highlight_row'`. + - Note: DELETE operation is executed on a row if an element has data attribute `data-action='delete'`. If `delete` action is given in `actions`, the function given for `delete` is executed on click of an element with `data-action='delete'` instead od executing DELETE operation. - `onhashchange`: `true` re-renders table on hashchange based on filters in URL hash. Set `false` to disable listening to hashchange (default `true`) - `table`: Shows the table control. Can be: - - `true`: displays a table (default) - - `'grid'`: renders a grid instead of a table - - `false`: disables the table (and shows nothing for the main content) + - `true`: displays a table (default) + - `'grid'`: renders a grid instead of a table + - `false`: disables the table (and shows nothing for the main content) - `count`: Shows the number of rows. Can be `true` (default) / `false` - `page`: Shows the page control. Can be `true` (default) / `false`. - `pageSize`: page size. Defaults to 100 @@ -115,13 +110,13 @@ The full list of options is below. Simple options can be specified as `data-` at - returns a dict with modified values of `data` and `meta` - `icon`: if `table: 'grid'` is used, display an icon. string / function that renders the cell. - function accepts an object with these keys: - - `row`: row data - - `data`: the dataset from `src` - - `index`: index of the row in the dataset from `src` - Example: - - `icon: 'fa fa-home fa-3x'` renders a FontAwesome home icon - - `icon: './path/to/image.png'` renders the image specified - - `icon: function(args) { return args.row['image_link'] }` renders an image with `src` attribute as the value from column name `image_link` + - `row`: row data + - `data`: the dataset from `src` + - `index`: index of the row in the dataset from `src` + - Example: + - `icon: 'fa fa-home fa-3x'` renders a FontAwesome home icon + - `icon: './path/to/image.png'` renders the image specified + - `icon: function(args) { return args.row['image_link'] }` renders an image with `src` attribute as the value from column name `image_link` **Advanced**. Each component can have a target which specifies a selector. For e.g., to render the export button somewhere else, use @@ -141,6 +136,7 @@ targets are: `data-search-template=""` will replace the search template with a simple input. Available template strings are: - `tableTemplate` +- `table_gridTemplate` - `countTemplate` - `pageTemplate` - `sizeTemplate` @@ -174,7 +170,7 @@ Features to be implemented: ## $.formhandler examples -Render a table using the FormHandler at `./data`: +### Render from a FormHandler ```html
@@ -183,22 +179,20 @@ Render a table using the FormHandler at `./data`: ``` - -Get data inside formhandler table: +### Access data inside formhandler ```html
``` - -Customize cell rendering to display a chart in a cell: +## Draw chart in cell ```html
@@ -217,7 +211,7 @@ Customize cell rendering to display a chart in a cell: ``` -In edit mode, show HTML input bindings like Dropdown, Datepicker, Number fields.. : +### Customize inputs in edit mode ```html @@ -241,11 +235,14 @@ In edit mode, show HTML input bindings like Dropdown, Datepicker, Number fields. name: 'c1', editable: { input: 'number', - attrs: { // keys and values in `attrs` will be added as + // keys and values in `attrs` will be added as + // + attrs: { min: 10, max: 100, - placeholder: '0 - 100' - } + placeholder: 'Age' + }, + validationMessage: 'Age must be between 0-100' } }, { diff --git a/docs/fuzzysearch.md b/docs/fuzzysearch.md new file mode 100644 index 0000000000000000000000000000000000000000..1634f96cef9b1953c378cb28b848be6dda206296 --- /dev/null +++ b/docs/fuzzysearch.md @@ -0,0 +1,47 @@ +# g1.fuzzysearch + +`g1.fuzzysearch(data, options)` returns a fuzzy search function that filteres +the data based on the text. + +For example: + +```js +var data = [ + {"product": "Cider Apple Vinegar"}, + {"product": "JBL In-Ear Headphones"}, + {"product": "Vaseline Body Lotion"}, + {"product": "Redux Men's Watch"}, + {"product": "Omega3 Fish Oil"}, +] + +var search = g1.fuzzysearch(data, { + keys: ['product'], // Search within these keys + limit: 2, // Return only the top 2 results +}) + +search('omega') +// Returns {product: "Omega3 Fish Oil", ...} since it's the only one +search('red') +// Returns {product: "Redux Men's Watch"} and {product: "JBL In-Ear Headphones"} +// The second matches r (in "Ear"), followed by e then d in "Headphones" +``` + +It matches with the following priority. For example, if the string is "alpha +beta", then: + +1. Match the exact phrase ("alpha beta") +2. Match all words in the same order ("alp bet") +3. Match words in any order ("bet alp") +4. Match partial words in any order ("ba aph") +5. Match letters in order ("abt") + +It accepts an `options` dict with these keys: + +- `keys`: a list of keys to search in. The keys are calculated and joined with a + space. (Default: assumes that data is a string list.) Each key can be either: + - a string (e.g. `"name"`, `"title"`) picks keys from the objects in the + `data` list. + - a function (e.g. `function (v) { return v['key'] })`) runs the function on + each element in the `data` list +- `limit`: the maximum number of results to return. (Default: `100`) +- `case`: `true` for case-sensitive comparisons. (Default: `false`) diff --git a/docs/template.html b/docs/template.html new file mode 100644 index 0000000000000000000000000000000000000000..581bb46cd20b263daf90ec49a97fb761d6f47d4b --- /dev/null +++ b/docs/template.html @@ -0,0 +1,3 @@ +This is the contents of the file "template.html". + +It is rendered as a template. 1 + 2 = <%- 1 + 2 %>. diff --git a/docs/template.md b/docs/template.md index 35d9c3a44f5e22cddd608c07332c131aa218d7c4..8ccceb6b531ecba18382d10e41622cf824816e85 100644 --- a/docs/template.md +++ b/docs/template.md @@ -20,14 +20,15 @@ This displays `Your platform is ...` and shows the userAgent just below the scri The template can use all global variables. You can pass additional variables using as `.template({var1: value, var2: value, ...})`. For example: + ```html - ``` @@ -45,21 +46,22 @@ for this to work. For example, this shows a circle in SVG bouncing around smoothly. + ```html - - + ``` @@ -77,42 +79,60 @@ To re-use the template or render the same template on a different DOM node, run `.template(data, {target: selector})`. This allows you to declare templates once and apply them across the body. For example: -```js -$('script.chart') - .template({heading: 'Dashboard 1'}, {target: '.dashboard1'}) - .template({heading: 'Dashboard 2'}, {target: '.dashboard2'}) - .template({}, {target: '.no-heading'}) + +```html +
+
+ + ``` -The target can also be specified via a `data-target=".dashboard1"` on the script -template. This is the same as specifying `{target: '.dashboard'}`. For example: +The target can also be specified via a `data-target=".panel1"` on the script +template. This is the same as specifying `{target: '.panel'}`. For example: ```html - - + + ``` ## $.template append -To append instead of replacing, run `.template(data, {append: true})`. Every -time `.template` is called, it appends rather than replaces. For example: +To append instead of replacing, use `data-append="true"`. Every time `.template` +is called, it appends rather than replaces. For example: -```js + +```html + + ``` -You can also specify this as ` -