Commit 59900777 authored by Tejesh's avatar Tejesh 🖖
Browse files

merge dev

parent 2750dc9b
Pipeline #77076 passed with stage
in 2 minutes and 43 seconds
# Change log
- `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.
......
......@@ -52,6 +52,10 @@ Examples:
- When the URL changes from `#a` to `#b`, it triggers 2 events on `window`:
- `.on('#', function(e) { e.hash.pathname == 'b' }`
- `.on('#/', function(e, val) { val == 'b' && e.old == 'a' }`
- Combinations of keys can be listened to simultaneously
- `.on('#?x #?y', function(e){})` will only be triggered if both x and y change
- When the hashkey is reset, `location.hash=''`
- `.on('#', function(e){})` as the location.hash is now `{}`
## $.urlchange events
......
......@@ -4,8 +4,9 @@
Example: Let's say the following HTML is on the page `/?city=NY`.
<!-- render:html -->
```html
<a class="urlfilter" href="?name=John">Link</a>
<a class="urlfilter" href="?name=John">Add ?name=John to URL</a>
<script>
$('body').urlfilter()
</script>
......@@ -26,21 +27,51 @@ current page URL instead of replacing it.
For example:
<!-- render:html -->
```html
<a class="urlfilter" href="?city=NY"> Change ?city= to NY</a>
<a class="urlfilter" href="?city=NY" data-mode="add"> Add ?city= to NY</a>
<a class="urlfilter" href="?city=NY" data-mode="del"> Remove NY from ?city=</a>
<a class="urlfilter" href="?city=NY" data-mode="toggle"> Toggle NY in ?city=</a>
<a class="urlfilter" href="?city=NY" data-target="pushState">Change ?city= to NY using pushState</a>
<a class="urlfilter" href="?city=NY" data-target="#"> Change location.hash, i.e. #?city= to NY</a>
<a class="urlfilter" href="?city=NY" data-target="iframe"> Change iframe URL ?city= NY</a>
<iframe src="?country=US"></iframe>
<a class="urlfilter" href="?city=NY" data-target=".block"> Use AJAX to load ?city=NY into .block</a>
<div class="block" src="?country=US"></div>
<script>
$('body').urlfilter() // Activate all the .urlfilter elements above
</script>
<li><a class="urlfilter" href="?city=NY"> Change ?city= to NY</a></li>
<li><a class="urlfilter" href="?city=NY" data-mode="add"> Add ?city= to NY</a></li>
<li><a class="urlfilter" href="?city=NY" data-mode="del"> Remove NY from ?city=</a></li>
<li><a class="urlfilter" href="?city=NY" data-mode="toggle"> Toggle NY in ?city=</a></li>
<li><a class="urlfilter" href="?city=NY" data-target="pushState">Change ?city= to NY using pushState</a></li>
<li><a class="urlfilter" href="?city=NY" data-target="#"> Change location.hash, i.e. #?city= to NY</a></li>
```
This works with `input`, `select` and `form` elements as well.
<!-- render:html -->
```html
<p><label><input type="checkbox" class="urlfilter" name="a" value="1" data-mode="toggle" data-target="#"> a=1</label></p>
<p>
<label><input type="radio" class="urlfilter" name="b" value="1" data-target="#"> b=1</label>
<label><input type="radio" class="urlfilter" name="b" value="2" data-target="#"> b=2</label>
</p>
<p><label><input type="range" class="urlfilter" name="c" data-target="#"> c=</label></p>
<p>
<select name="d" class="urlfilter" data-target="#">
<option></option>
<option>1</option>
<option>2</option>
</select>
</p>
<p>
<form class="urlfilter" data-target="#">
<input name="x" placeholder="x value">
<input name="y" placeholder="y value">
<button name="z" value="z2" type="submit">Submit</button>
</form>
</p>
```
You can target an IFrame or DOM element to change the URL:
<!-- TODO: check these examples. Not working -->
```html
<p><a class="urlfilter" href="?city=NY" data-target="iframe">Change iframe URL ?city= NY</a></p>
<iframe src="?country=US"></iframe>
<p><a class="urlfilter" href="?city=NY" data-target=".block"> Use AJAX to load ?city=NY into .block</a></p>
<div class="block" src="?country=US"></div>
```
......@@ -64,6 +95,8 @@ Triggers support these attributes:
- `toggle` - toggles the query key and value combination
- `data-remove="true"`: removes query parameters without values. e.g. `?x&y=1` becomes `?y=1`
- `data-src` changes which attribute holds the current URL when `data-target=` is a selector. Default: `src`
- for input fields like checkboxes, an `id` or `name` and the `value` attribute is mandatory. e.g
`<input type="checkbox" id="checkbox" value="x">` will add `?checkbox=x` to the URL
Containers support these attributes:
......
{
"name": "g1",
"version": "0.13.1",
"version": "0.14.0",
"description": "Gramex 1.x interaction library",
"license": "MIT",
"author": "S Anand <s.anand@gramener.com>",
......
import { parse } from './url.js'
import { hasdata } from './_util.js'
var container_options = {
attr: 'href',
event: 'click change submit',
selector: '.urlfilter',
src: 'src'
}
var event_namespace = '.urlfilter'
export function urlfilter(options) {
options = options || {}
var $self = this
// If there are no elements in the selection, exit silently
if ($self.length == 0)
return
var doc = $self[0].ownerDocument
var attr = options.attr || $self.data('attr') || 'href'
var event = options.event || $self.data('event') || 'click'
var selector = options.selector || $self.data('selector') || '.urlfilter'
var default_src = options.src || $self.data('src') || 'src'
var default_mode = options.mode || $self.data('mode')
var default_target = options.target || $self.data('target')
var default_remove = options.remove || hasdata($self, 'remove')
var off = options.off || hasdata($self, 'off')
var settings = $.extend({}, container_options, options || {}, this.dataset)
var default_remove = settings.remove || hasdata($self, 'remove')
var events = settings.event.split(/\s+/).map(function (v) { return v + event_namespace }).join(' ')
// options.location and options.history are used purely for testing
var loc = options.location || (doc.defaultView || doc.parentWindow).location
var hist = options.history || (doc.defaultView || doc.parentWindow).history
if (off)
return $self.off(event + '.urlfilter')
var loc = settings.location || (doc.defaultView || doc.parentWindow).location
var hist = settings.history || (doc.defaultView || doc.parentWindow).history
return $self
.on(event + '.urlfilter', selector, function (e) {
e.preventDefault()
.on(events, settings.selector, function (e) {
var $this = $(this),
mode = $this.data('mode') || default_mode,
target = $this.data('target') || default_target,
src = $this.data('src') || default_src,
remove = hasdata($this, 'remove', default_remove)
var href
if (e.type == 'click')
href = $this.attr(attr)
else if (e.type == 'submit')
href = '?' + $this.serialize()
else if (e.type == 'input' || e.type == 'change') {
mode = $this.data('mode') || settings.mode,
target = $this.data('target') || settings.target,
src = $this.data('src') || settings.src,
remove = hasdata($this, 'remove', default_remove),
href
if (e.type == 'change' || $(e.target).is(':input:not(:button)')) {
var key = encodeURIComponent($this.attr('id') || $this.attr('name'))
var val = encodeURIComponent($this.val())
href = '?' + key + '=' + val
}
else if (e.type == 'submit' || $(e.target).is('form')) {
e.preventDefault()
href = '?' + $this.serialize()
}
else if (e.type == 'click') {
if ($(e.target).is('a'))
e.preventDefault()
href = $this.attr(settings.attr)
} else
return
var url = parse(href),
q = url.searchList
......@@ -62,14 +62,12 @@ export function urlfilter(options) {
return result.toString()
}
/*
If the target is... the URL is get/set at
------------------------ ---------------------
unspecified (=> window) location.href
'pushState' location.href
'#' location.hash
anything else $(target).data(src)
*/
// If the target is... the URL is get/set at
// ------------------------ ---------------------
// unspecified (=> window) location.href
// 'pushState' location.href
// '#' location.hash
// anything else $(target).data(src)
if (!target)
loc.href = target_url(loc.href)
else if (target == '#')
......
......@@ -89,6 +89,27 @@
window.location.hash = '#?x=1&y=2'
})
tape('clearing x should still trigger an event', function(t) {
reset('#?x=1')
t.plan(2) // One less than no. of tests. #?x.test should not be fired
$(window).one('#?x', function (e, val) {
t.deepEqual(e.hash.searchList, {})
t.deepEqual(e.old.searchList, {'x': ['1']})
})
window.location.hash = ''
})
tape('Adding #?abc=1&xyz=2 triggers on both abc and xyz events', function(t) {
reset('#?abc=1&xyz=1')
t.plan(3) // One less than no. of tests. #?x.test should not be fired
$(window).one('#?abc #?xyz', function (e, val) {
t.equal(val, '2')
t.deepEqual(e.hash.searchList, { 'abc': ['1'], 'xyz': ['2'] })
t.deepEqual(e.old.searchList, { 'abc': ['1'], 'xyz': ['1'] })
})
window.location.hash = '#?abc=1&xyz=2'
})
tape('#a?x=1&y=2&z=3 -> #b?x=1&x=2&y=3', function(t) {
reset('#a?x=1&y=2&z=3')
t.plan(18)
......
......@@ -4,6 +4,8 @@
<head>
<title>urlfilter tests</title>
<script src="../node_modules/jquery/dist/jquery.min.js"></script>
<link rel="stylesheet" href="../node_modules/bootstrap/dist/css/bootstrap.css">
<script src="../node_modules/bootstrap/dist/js/bootstrap.js"></script>
<script src="../dist/event.min.js"></script>
<script src="../dist/urlfilter.min.js"></script>
<script src="../node_modules/component-emitter/index.js"></script>
......@@ -69,6 +71,9 @@
<i class="urlfilter base" href="?x=1">?x=1</i>
<div class="urlfilter base" href="?x=1">?x=1</div>
<button class="urlfilter base" href="?x=1">?x=1</button>
<div>
<input type="checkbox" class="urlfilter base" data-mode="toggle" id="checkbox" value="x" checked>
</div>
<script>
tape('clicking any element sets location.href to a page with an UPDATED URL', function (t) {
check(t, 'a.urlfilter.base', 'href', '?y=1', 'y=1&x=1')
......@@ -76,6 +81,10 @@
check(t, 'div.urlfilter.base', 'href', '?y=1', 'y=1&x=1')
check(t, 'button.urlfilter.base', 'href', '?y=1', 'y=1&x=1')
})
tape('Events on checkbox should set location.href to a page with UPDATED URL', function(t){
check(t, '#checkbox', 'href', '?y=1', 'y=1&checkbox=x')
check(t, '#checkbox', 'href', '?y=1', 'y=1&checkbox=x', 'change')
})
tape('the URL is updated, irrespective of the current URL', function (t) {
check(t, 'a.urlfilter.base', 'href', '', 'x=1')
check(t, 'a.urlfilter.base', 'href', '?x', 'x=1')
......@@ -85,7 +94,7 @@
})
</script>
<a class="urlfilter def x1" href="?x=1" data-mode="">set ?x=1</a>
<a class="urlfilter def x1" href="?x=1" data-mode="">set ?x=1< fddfgdf</a>
<a class="urlfilter add x1" href="?x=1" data-mode="add">add ?x=1</a>
<a class="urlfilter tog x1" href="?x=1" data-mode="toggle">toggle ?x=1</a>
<a class="urlfilter del x1" href="?x=1" data-mode="del">toggle ?x=1</a>
......@@ -174,24 +183,24 @@
<!-- .default-section -->
<section class="default-input-section" data-event="input">
<input type="range" class="urlfilter base" name="slider">
<input type="range" class="urlfilter slider" name="slider">
<script>
$('.default-input-section').urlfilter({ location: loc, history: hist, event: 'input' })
tape('clicking any element sets location.href to a page with an UPDATED URL', function (test) {
test.plan(3)
test.test('test slider no input', function (t) {
check(t, 'input.urlfilter.base', 'href', '?slider=50', 'slider=50', 'input')
check(t, 'input.urlfilter.slider', 'href', '?slider=50', 'slider=50', 'input')
})
// update slider
test.test('test slider with change in val', function (t) {
$('input.urlfilter.base').val(80)
check(t, 'input.urlfilter.base', 'href', '?slider=80', 'slider=80', 'input')
$('input.urlfilter.slider').val(80)
check(t, 'input.urlfilter.slider', 'href', '?slider=80', 'slider=80', 'input')
})
// update name attr and update slider
test.test('test slider with change in name of <input> element', function (t) {
$('input.urlfilter.base').attr('name', 'slider_renamed')
$('input.urlfilter.base').val(60)
check(t, 'input.urlfilter.base', 'href', '?slider_renamed=620', 'slider_renamed=60', 'input')
$('input.urlfilter.slider').attr('name', 'slider_renamed')
$('input.urlfilter.slider').val(60)
check(t, 'input.urlfilter.slider', 'href', '?slider_renamed=620', 'slider_renamed=60', 'input')
})
})
</script>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment