Skip to content

Commit

Permalink
Merge branch 'dev'
Browse files Browse the repository at this point in the history
  • Loading branch information
cheton committed May 21, 2016
2 parents 197efa7 + 9487d2c commit aea82b2
Show file tree
Hide file tree
Showing 9 changed files with 188 additions and 64 deletions.
14 changes: 13 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,20 +1,32 @@
sudo: required
dist: trusty
group: edge

language: node_js

os:
- linux

node_js:
- '6'
- '5'
- '4'
- '0.12'
- '0.10'
- 'iojs'

after_success:
- npm run coveralls
- npm run coverage-clean

before_deploy:
- echo "Deploying to GitHub releases"
- ls -al releases

deploy:
provider: releases
api_key:
secure: "x9nz3bvNesYVCesjj36yFYlYIAVykchBR4Ffzzysd4Tk1v+0eh0mRc9jmTzfF7xYsAjpKRCMGCjWG39aPwVG7rbs0EZDrXVxT7KObZ31HS9A1VWkOs/LKAlDrwjylx4umNswmVWAW+pVr9N431Be21+mZg4Xu8z6iDnLgHWxhK9n2IewKanPVV3pbB6hNVKpshnbYMraqwnJQE4gOVhBc2EBHUAUIhtVN1ntmRL76+trlpPFTzbhBVywf0TRvW4J67wYQO0was/qRww+wKmUvymD+7vk8P/23+uVi9pDpUix2TMZfyCPUG1PpQ0cZfIaaUg4POQD3hqFCJGeAgxZzIPEHOVd+TLF+B2eZjSMlTDyrVI2+JzVwx9SIPBkLgsRy1xNGFfMHXidJGOnkG9efv2artjkNblx3SGkx9EgAd1fsfM/epvggaJvW3rsU0AlRN9IKOeHToYVkWGJIJNjFGt1AL7a98SvtQ56xsXocUeLjLRnh14VFxZ22IeBRClOpyMGVLuTBy+m4hJMSB8JbjdBkJW45Ou6Pdswt5cW6WWXM1sepmxjttStp0FyiOr0qCkQfJsEEg1fYF0Rj7zNfUTFlRCX9+JWhQ/Lb61kEsBjqKc7/lPFOiKB/iLkQo+gQNb5ToaQMZIK0vmYf4gZZ6tkFkicbp8JjZu6mlNKdSE="
secure: "MZfhBihMNxpAGUffDpp5u5KUfhJ6+g0PQ7h7lbTl19HBK9zCnvN5Go8xJYGCZQNj4Y2bGwsXokGN3PudIJwhTMX3LnOEoByoqWUPw5wUpeRlRO3B7v9GFYsJM2Y9/ZkjEmv0bFwkSC69OMcQeVOZET83ch8UYl7ftIXGp2iTDF8LLCtWjDWRfdQOkDrd44JO2DLIVc5sbpbT4jEklln09ZJBAlbKTTpAiAPXLVn9WqZWiWMlbWJVKczykLrvkTlAUAJlZpu+2yqFmGlCQzWS/Ksc/2z1cvFKbC1mkZdfm+g3SUX1CJtjOAJjc9iAdltbcU4VqkwgFHVDYAa9wKU18fNw5nsYECEHdQx42GU+cCnhTEzKKMJdWj+h+QgWeMgCyUncBWubNiiU2fI0QtC8LUs19IppQ0/nbFR7RihvtILiaxfcQ37E42PGzFFdP1JnmthEXN4g4FV8sTXOsTtxCPKSlpea65NJyQheztzhOyromohT06EtLSjpwtwUnKMJmBNvjWo48IlOI5QPqbSOuI/wT/Yow2JuJVr4rQj4VKNYSDFwKYdo+ltdgfSjbsfKCevCw1Ok1QLHYcdUfOolzLJzNkWemEtfC4hdEkBB0iz3paznGvE9IggqAXZyvZuwxxFhNSRiZPujhOu4GsCtu3UvlOv8wsUeHJ3s2A0f0Qs="
file_glob: true
file:
- 'releases/*.*'
Expand Down
47 changes: 47 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,8 @@ console.log(node.getFirstChild().getPreviousSibling());
#### Events Usage
Learn more: [Events](https://github.com/cheton/infinite-tree/wiki/Events)
```js
tree.on('click', function(event) {
});
tree.on('contentWillUpdate', function() {
});
tree.on('contentDidUpdate', function() {
Expand All @@ -122,6 +124,51 @@ tree.on('selectNode', function(node) {
* [Functions: Node](https://github.com/cheton/infinite-tree/wiki/Functions:-Node)
* [Events](https://github.com/cheton/infinite-tree/wiki/Events)

## FAQ

#### How to attach click event listeners to nodes?

Use <b>event delegation</b> <sup>[[1](http://javascript.info/tutorial/event-delegation), [2](http://davidwalsh.name/event-delegate)]</sup>

```js
// JavaScript
var el = document.querySelector('#tree');
var tree = new InfiniteTree(el, { /* options */ });

tree.on('click', function(event) {
event = event || window.event;
var target = event.target || event.srcElement;

// do stuff with node
console.log(target);

// Check if the target element contains a specific class
if (!hasClass(target, 'my-specific-class')) {
return;
}
};

// Checks if an element contains a specific class
var hasClass = function(el, className) {
if (!el) {
return false;
}
var classes = el.className.split(' ');
return (classes.indexOf(className) >= 0);
};
```
Event delegation with jQuery:
```js
var el = document.querySelector('#tree');
var tree = new InfiniteTree(el, { /* options */ });

// jQuery
$(tree.contentElement).on('click', 'your-event-selector', function() {
// do stuff with node
});
```
## License
Copyright (c) 2016 Cheton Wu
Expand Down
88 changes: 58 additions & 30 deletions dist/infinite-tree.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/*! infinite-tree v1.1.1 | (c) 2016 Cheton Wu <[email protected]> | MIT | https://github.com/cheton/infinite-tree */
/*! infinite-tree v1.2.0 | (c) 2016 Cheton Wu <[email protected]> | MIT | https://github.com/cheton/infinite-tree */
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
Expand Down Expand Up @@ -162,43 +162,71 @@ return /******/ (function(modules) { // webpackBootstrap
_this.draggableTarget = null;
_this.droppableTarget = null;
_this.contentListener = {
'click': function click(e) {
var itemTarget = null;
var clickToggler = false;
'click': function click(event) {
event = event || window.event;

// Wrap stopPropagation that allows click event handler to stop execution
// by setting the cancelBubble property
var stopPropagation = event.stopPropagation;
event.stopPropagation = function () {
// Setting the cancelBubble property in browsers that don't support it doesn't hurt.
// Of course it doesn't actually cancel the bubbling, but the assignment itself is safe.
event.cancelBubble = true;

if (stopPropagation) {
stopPropagation.call(event);
}
};

if (e.target && e.currentTarget) {
itemTarget = e.target !== e.currentTarget ? e.target : null;
} else if (e.srcElement) {
// IE8
itemTarget = e.srcElement;
}
// Call setTimeout(fn, 0) to re-queues the execution of subsequent calls, it allows the
// click event to bubble up to higher level event handlers before handling tree events.
setTimeout(function () {
// Stop execution if the cancelBubble property is set to true by higher level event handlers
if (event.cancelBubble === true) {
return;
}

while (itemTarget && itemTarget.parentElement !== _this.contentElement) {
if ((0, _helper.hasClass)(itemTarget, _this.options.togglerClass)) {
clickToggler = true;
// Emit 'click' event
_this.emit('click', event);

// Stop execution if the cancelBubble property is set to true after emitting the click event
if (event.cancelBubble === true) {
return;
}
itemTarget = itemTarget.parentElement;
}

if (!itemTarget) {
return;
}
var itemTarget = null;
var clickToggler = false;

var id = itemTarget.getAttribute(_this.options.nodeIdAttr);
var node = _this.getNodeById(id);
if (event.target && event.currentTarget) {
itemTarget = event.target !== event.currentTarget ? event.target : null;
} else if (event.srcElement) {
// IE8
itemTarget = event.srcElement;
}

if (!node) {
return;
}
while (itemTarget && itemTarget.parentElement !== _this.contentElement) {
if ((0, _helper.hasClass)(itemTarget, _this.options.togglerClass)) {
clickToggler = true;
}
itemTarget = itemTarget.parentElement;
}

// Click on the toggler to open/close a tree node
if (clickToggler) {
_this.toggleNode(node);
return;
}
if (!itemTarget) {
return;
}

var id = itemTarget.getAttribute(_this.options.nodeIdAttr);
var node = _this.getNodeById(id);
if (!node) {
return;
}

// Click on the toggler to open/close a tree node
if (clickToggler) {
_this.toggleNode(node);
return;
}

// Use setTimeout(fn, 0) to re-queues the selectNode operation, it allows the click event to bubble up to higher level event handlers.
setTimeout(function () {
_this.selectNode(node); // selectNode will re-render the tree
}, 0);
},
Expand Down
6 changes: 3 additions & 3 deletions dist/infinite-tree.min.js

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions examples/classic/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ const tree = new InfiniteTree(document.querySelector('#classic [data-id="tree"]'
}
});

tree.on('click', (event) => {
console.log('click', event);
});
tree.on('contentWillUpdate', () => {
console.log('contentWillUpdate');
});
Expand Down
3 changes: 3 additions & 0 deletions examples/default/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ const tree = new InfiniteTree(document.querySelector('#default [data-id="tree"]'
}
});

tree.on('click', (event) => {
console.log('click', event);
});
tree.on('contentWillUpdate', () => {
console.log('contentWillUpdate');
});
Expand Down
3 changes: 3 additions & 0 deletions examples/filebrowser/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ const tree = new InfiniteTree(document.querySelector('#filebrowser [data-id="tre
}
});

tree.on('click', (event) => {
console.log('click', event);
});
tree.on('contentWillUpdate', () => {
console.log('contentWillUpdate');
});
Expand Down
4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "infinite-tree",
"version": "1.1.1",
"version": "1.2.0",
"description": "A browser-ready tree library that can efficiently display a large amount of data using infinite scrolling.",
"homepage": "https://github.com/cheton/infinite-tree",
"main": "lib/index.js",
Expand All @@ -11,7 +11,7 @@
"pack-examples": "npm run build-examples && zip -r examples.zip examples/{dist,vendor,*.html,*.css}",
"test": "./babel-tap --coverage test/*.js",
"dist": "webpack; BUILD_ENV=dist webpack",
"release": "mkdir -p releases; cp -f dist/infinite-tree.css releases/infinite-tree-${npm_package_version}.css; cp -f dist/infinite-tree.js releases/infinite-tree-${npm_package_version}.js; cp -f dist/infinite-tree.min.js releases/infinite-tree-${npm_package_version}.min.js",
"release": "mkdir -p releases; rm -f releases/*; cp -f dist/infinite-tree.css releases/infinite-tree-${npm_package_version}.css; cp -f dist/infinite-tree.js releases/infinite-tree-${npm_package_version}.js; cp -f dist/infinite-tree.min.js releases/infinite-tree-${npm_package_version}.min.js",
"lint": "npm run eslint && npm run stylint",
"eslint": "eslint ./src",
"eslint:fix": "eslint --fix ./src",
Expand Down
84 changes: 56 additions & 28 deletions src/infinite-tree.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,42 +63,70 @@ class InfiniteTree extends events.EventEmitter {
droppableTarget = null;

contentListener = {
'click': (e) => {
let itemTarget = null;
let clickToggler = false;
'click': (event) => {
event = event || window.event;

// Wrap stopPropagation that allows click event handler to stop execution
// by setting the cancelBubble property
const stopPropagation = event.stopPropagation;
event.stopPropagation = function() {
// Setting the cancelBubble property in browsers that don't support it doesn't hurt.
// Of course it doesn't actually cancel the bubbling, but the assignment itself is safe.
event.cancelBubble = true;

if (stopPropagation) {
stopPropagation.call(event);
}
};

if (e.target && e.currentTarget) {
itemTarget = (e.target !== e.currentTarget) ? e.target : null;
} else if (e.srcElement) { // IE8
itemTarget = e.srcElement;
}
// Call setTimeout(fn, 0) to re-queues the execution of subsequent calls, it allows the
// click event to bubble up to higher level event handlers before handling tree events.
setTimeout(() => {
// Stop execution if the cancelBubble property is set to true by higher level event handlers
if (event.cancelBubble === true) {
return;
}

while (itemTarget && itemTarget.parentElement !== this.contentElement) {
if (hasClass(itemTarget, this.options.togglerClass)) {
clickToggler = true;
// Emit 'click' event
this.emit('click', event);

// Stop execution if the cancelBubble property is set to true after emitting the click event
if (event.cancelBubble === true) {
return;
}
itemTarget = itemTarget.parentElement;
}

if (!itemTarget) {
return;
}
let itemTarget = null;
let clickToggler = false;

const id = itemTarget.getAttribute(this.options.nodeIdAttr);
const node = this.getNodeById(id);
if (event.target && event.currentTarget) {
itemTarget = (event.target !== event.currentTarget) ? event.target : null;
} else if (event.srcElement) { // IE8
itemTarget = event.srcElement;
}

if (!node) {
return;
}
while (itemTarget && itemTarget.parentElement !== this.contentElement) {
if (hasClass(itemTarget, this.options.togglerClass)) {
clickToggler = true;
}
itemTarget = itemTarget.parentElement;
}

// Click on the toggler to open/close a tree node
if (clickToggler) {
this.toggleNode(node);
return;
}
if (!itemTarget) {
return;
}

const id = itemTarget.getAttribute(this.options.nodeIdAttr);
const node = this.getNodeById(id);
if (!node) {
return;
}

// Click on the toggler to open/close a tree node
if (clickToggler) {
this.toggleNode(node);
return;
}

// Use setTimeout(fn, 0) to re-queues the selectNode operation, it allows the click event to bubble up to higher level event handlers.
setTimeout(() => {
this.selectNode(node); // selectNode will re-render the tree
}, 0);
},
Expand Down

0 comments on commit aea82b2

Please sign in to comment.