Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Initial commit

  • Loading branch information...
commit a33fdc7f3853e50cb0f687b19200ad6c3e9e3dad 0 parents
@matthewmueller authored
2  .gitignore
@@ -0,0 +1,2 @@
+components
+build
11 Makefile
@@ -0,0 +1,11 @@
+
+build: components index.js list.css
+ @component build --dev
+
+components: component.json
+ @component install --dev
+
+clean:
+ rm -fr build components template.js
+
+.PHONY: clean
121 Readme.md
@@ -0,0 +1,121 @@
+
+# list
+
+Generic list component, based on the [menu component](https://github.com/component/menu).
+
+## Installation
+
+ $ component install matthewmueller/list
+
+## Features
+
+* Custom templating support, using [minstache](https://github.com/visionmedia/minstache).
+* Events for composition
+* Structural CSS
+* Fluent API
+
+## Events
+
+* `add` (item) when an item is added
+* `remove` (item) when an item is removed
+* `select` (item) when an item is selected
+
+Also, list item slugs are emitted when clicked.
+
+ list.add('First Item')
+ list.on('select:0', fn)
+
+## Example
+
+### Message Template:
+
+ <script type="text/template" id="message">
+ <a href='#'>
+ <span class='from'>{from}</span>
+ <span class='subject'>{subject}</span>
+ <span class='message'>{message}</span>
+ </a>
+ </script>
+
+### Usage:
+
+ var List = require('list'),
+ inbox = new List;
+
+ inbox.template(document.getElementById('message').text)
+
+ var messages = [
+ { from : 'jim', subject : 'hey', message : 'blah'},
+ { from : 'matt', subject : 'sup', message : 'cool'},
+ { from : 'drew', subject : 'howdy', message : 'yah'},
+ ]
+
+ inbox.add(messages, function(message) {
+ console.log('invoked fn', message);
+ })
+
+ inbox.el.appendTo('body');
+
+ inbox.on('add', function(message) {
+ console.log('message added:', message);
+ });
+
+ inbox.on('remove', function(message) {
+ console.log('message removed:', message);
+ })
+
+ inbox.on('select', function(message) {
+ console.log('message selected:', message);
+ });
+
+ inbox.add({
+ from : 'zak',
+ subject : 'no way',
+ message : 'crazy'
+ });
+
+ inbox.remove(3);
+
+## API
+
+### List()
+
+Create a new `List`:
+
+var List = require('list');
+var list = new List();
+var list = List();
+
+### List#template(str)
+
+Add a template string to be used when adding items. The internal templating engine is [minstache](https://github.com/visionmedia/minstache).
+
+ list.template('<li><a href={url}>{text}</a></li>')
+
+### List#add(arr|obj, [fn])
+
+Add a new list item(s). Pass each `obj` into the templating function. When `selected` the optional callback `fn` will be invoked.
+
+ list.add({ name : 'apple' }, function(item) {
+ console.log('You selected:', item.name);
+ })
+
+You can also use text and the default template:
+
+ list.add('apple'); // <li><a href="#">apple</a></li>
+
+### List#remove(i)
+
+Remove an item by it's place in the list
+
+ list.remove(0);
+
+### List.has(i)
+
+Checks to see if an item exists.
+
+ list.has(1);
+
+## License
+
+ MIT
19 component.json
@@ -0,0 +1,19 @@
+{
+ "name": "list",
+ "repo": "matthewmueller/list",
+ "description": "Generic list component",
+ "version": "0.0.1",
+ "keywords": [],
+ "dependencies": {
+ "component/jquery" : "*",
+ "matthewmueller/emitter" : "*",
+ "visionmedia/minstache" : "*"
+ },
+ "development": {},
+ "scripts": [
+ "index.js"
+ ],
+ "styles": [
+ "list.css"
+ ]
+}
127 index.js
@@ -0,0 +1,127 @@
+/**
+ * Module dependencies
+ */
+
+var $ = require('jquery'),
+ Emitter = require('emitter'),
+ mu = require('minstache');
+
+/**
+ * Expose `List`.
+ */
+
+module.exports = List;
+
+/**
+ * Initialize a new `List`
+ */
+
+function List() {
+ if(!(this instanceof List)) return new List;
+ Emitter.call(this);
+ this.items = {};
+ this.cid = 0;
+ this.el = $('<ul class="list">');
+}
+
+/**
+ * Add templating
+ *
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.template = function(str) {
+ this.tpl = mu.compile('<li>' + str + '</li>');
+};
+
+/**
+ * Default template
+ *
+ * @return {String}
+ * @api private
+ */
+
+List.prototype.tpl = function(text) {
+ return '<li><a href="#">' + text + '</a></li>';
+};
+
+/**
+ * Add list item with the given `arr` and optional callback `fn`.
+ * Emits an `add` event with the supplied `obj`.
+ *
+ * When the item is clicked `fn()` will be invoked, along with firing a
+ * `select` event. If a `slug` is present, it will also fire the event
+ * `slug`, passing the `obj`.
+ *
+ * @param {Array} arr
+ * @param {Function} fn
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.add = function(arr, fn) {
+ arr = Array.isArray(arr) ? arr : [arr];
+ var len = arr.length;
+
+ for(var i = 0; i < len; i++) this.addItem(arr[i], fn);
+ return this;
+};
+
+/**
+ * Add a single list item
+ *
+ * @param {Object} obj
+ * @param {Function} fn
+ */
+
+List.prototype.addItem = function(obj, fn) {
+ var self = this,
+ cid = this.cid++,
+ el = $(this.tpl(obj));
+
+ el.addClass('list-item-' + cid)
+ .appendTo(this.el)
+ .click(function(e) {
+ e.preventDefault();
+ e.stopPropagation();
+ self.emit('select', obj);
+ self.emit('select:'+cid, obj);
+ if(fn) fn(obj);
+ });
+
+ this.emit('add', obj);
+ this.items[cid] = obj;
+
+ return this;
+};
+
+/**
+ * Remove items from the list
+ *
+ * @param {Number} cid
+ * @return {List}
+ * @api public
+ */
+
+List.prototype.remove = function(cid) {
+ var item = this.el.find('.list-item-' + cid);
+ if (!item) throw new Error('no list item named "' + cid + '"');
+ this.emit('remove', this.items[cid]);
+ this.emit('remove:'+cid, this.items[cid]);
+ item.remove();
+ delete this.items[cid];
+ return this;
+};
+
+/**
+ * Check if this list has an item with the given `slug`.
+ *
+ * @param {String} slug
+ * @return {Boolean}
+ * @api public
+ */
+
+List.prototype.has = function(cid){
+ return !! (this.items[cid]);
+};
27 list.css
@@ -0,0 +1,27 @@
+.list {
+ margin: 0;
+ padding: 0;
+ border: 1px solid rgba(0,0,0,0.2);
+}
+
+.list li {
+ list-style: none;
+}
+
+.list li a {
+ display: block;
+ padding: 5px 30px 5px 12px;
+ text-decoration: none;
+ border-top: 1px solid #eee;
+ color: #2e2e2e;
+ outline: none;
+}
+
+.list li:first-child a {
+ border-top: none;
+}
+
+.list li a:hover,
+.list li.selected a {
+ background: #f1faff;
+}
57 test/index.html
@@ -0,0 +1,57 @@
+<html>
+<head>
+ <title>List Component</title>
+ <link rel="stylesheet" href="../build/build.css">
+</head>
+<body>
+ <h2>List Component</h2>
+ <script src="../build/build.js" type="text/javascript"></script>
+ <script type="text/template" id="message">
+ <a href='#'>
+ <span class='from'>{from}</span>
+ <span class='subject'>{subject}</span>
+ <span class='message'>{message}</span>
+ </a>
+ </script>
+
+ <script type="text/javascript">
+ var List = require('list'),
+ inbox = new List;
+
+ inbox.template(document.getElementById('message').text)
+
+ var messages = [
+ { from : 'jim', subject : 'hey', message : 'blah'},
+ { from : 'matt', subject : 'sup', message : 'cool'},
+ { from : 'drew', subject : 'howdy', message : 'yah'},
+ ]
+
+ inbox.add(messages, function(message) {
+ console.log('invoked fn', message);
+ })
+
+ inbox.el.appendTo('body');
+
+ inbox.on('add', function(message) {
+ console.log('message added:', message);
+ });
+
+ inbox.on('remove', function(message) {
+ console.log('message removed:', message);
+ })
+
+ inbox.on('select', function(message) {
+ console.log('message selected:', message);
+ });
+
+ inbox.add({
+ from : 'zak',
+ subject : 'no way',
+ message : 'crazy'
+ });
+
+ inbox.remove(3);
+
+ </script>
+</body>
+</html>
Please sign in to comment.
Something went wrong with that request. Please try again.