Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

quick hack to move things around

  • Loading branch information...
commit 72a0400e36f54262368891b03e93726deb96b8d7 1 parent c6a6687
@rixth authored
View
4 index.html
@@ -27,7 +27,7 @@
</h1>
<p>
- A simple <a href="http://jqueryui.com">jQuery UI</a> widget to manage a list of items. It's fully unit tested too, you can <a href="tests.html">run the tests</a> if you like.
+ A simple <a href="http://jqueryui.com">jQuery UI</a> widget to manage a list of items. It's fully unit tested too, you can <a href="test/spec-runner.html">run the tests</a> if you like.
</p>
<h2>Example</h2>
@@ -38,7 +38,7 @@
</div>
<pre id="debug_log">Loading...</pre>
- <h2>You might also like...</h2>
+ <h2 style="clear:both;padding-top: 10px">You might also like...</h2>
<p>I've made a couple other form related jQuery UI widgets, <a href="http://rixth.github.com/customSelect/">jquery.customSelect</a> and <a href="http://rixth.github.com/customRadio/">jquery.customRadio</a>.</p>
<h2 style="clear:both;padding-top:10px;">Download</h2>
View
39 src/bubbleBox.css
@@ -0,0 +1,39 @@
+.ui-bubblebox-list {
+ list-style: none;
+ padding: 0;
+ margin: 10px 0;
+}
+
+.ui-bubblebox-item {
+ border:1px solid #cdd5e6;
+ background:#eff2f7;
+ color:#6a6a6a;
+ border-radius: 3px;
+ -moz-border-radius: 3px;
+
+ padding: 5px 15px 5px 5px;
+ margin: 5px 0;
+
+ position: relative;
+}
+
+.ui-bubblebox-item span {
+ display: block;
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.ui-bubblebox-removeItem {
+ font-size:12px;
+ font-weight:bold;
+ cursor:pointer;
+ color:#abb8d4;
+
+ position: absolute;
+ right: 5px;
+ top: 5px;
+}
+.ui-bubblebox-removeItem:hover {
+ color: #bbb;
+}
View
89 src/jquery.bubbleBox.js
@@ -0,0 +1,89 @@
+/*! bubbleBox: a jQuery UI widget to manage a list of items
+ http://github.com/rixth/bubbleBox
+*/
+
+/*jshint browser: true, jquery: true, indent: 2, white: true, curly: true, forin: true, noarg: true, immed: true, newcap: true, noempty: true */
+(function ($) {
+ $.widget("ui.bubbleBox", {
+ options: {
+ showRemoveButton: true,
+ list: null,
+ allowDupes: false,
+ seedData: [],
+ triggerKeyCodes: [
+ 13, // enter
+ 44, 188, // the two possibilities for comma
+ 59, 186 // the two possibilities for semicolon
+ ]
+ },
+ _create: function () {
+ var self = this;
+
+ self.input = self.element;
+
+ self.options.list || (self.options.list = '#' + self.input.attr('id') + '_list');
+ self.list = $(self.options.list).addClass('ui-bubblebox-list');
+
+ // Bind events
+ if (self.options.showRemoveButton) {
+ self.list.delegate('.ui-bubblebox-removeItem', 'click', function (event) {
+ self.removeItem($(this.parentNode));
+ });
+ }
+
+ self.element.bind('blur keydown', function (event) {
+ var newValue = self.input.val();
+
+ if (event.type === 'blur' || jQuery.inArray(event.which, self.options.triggerKeyCodes) !== -1) {
+ if (self.addItem(newValue, event)) {
+ self.input.val('');
+ event.preventDefault();
+ }
+ } else if (newValue === '' && event.type === 'keydown' && event.which === 8) {
+ self.removeItem(self.list.find('li:last-child'));
+ }
+ });
+
+ // Insert start data
+ $(self.options.seedData).each(function () {
+ self.addItem(this);
+ });
+ },
+ _createBubble: function (value) {
+ var removeButton = this.options.showRemoveButton ? '<div class="ui-bubblebox-removeItem">x</div>' : '';
+ return $('<li class="ui-bubblebox-item"><span>' + value + '</span>' + removeButton + '</li>');
+ },
+ val: function () {
+ var values = [];
+ this.list.children().each(function () {
+ values.push($(this).find('span').text());
+ });
+ return values;
+ },
+ removeItem: function (item, event) {
+ item.remove();
+ this._trigger('remove', event, { value: item.find('span').text(), node: item[0] });
+ },
+ addItem: function (value, event) {
+ var self = this,
+ bubble;
+
+ if (!self.options.allowDupes && jQuery.inArray(value, self.val()) !== -1) {
+ return false;
+ }
+
+ if (value !== '' && !value.match(/^\s+$/) && self._trigger('beforeAdd', event, { value: value }) !== false) {
+ bubble = self._createBubble(value);
+ self.list.append(bubble);
+ self._trigger('afterAdd', event, { value: value, node: bubble[0] });
+ return bubble;
+ } else {
+ return false;
+ }
+ },
+ _destroy: function () {
+ this.list.empty().removeClass('ui-bubblebox-list');
+ $.Widget.prototype.destroy.apply(this, arguments);
+ }
+ });
+}(jQuery));
View
194 test/bubbleBox.spec.js
@@ -0,0 +1,194 @@
+/*globals jasmine, describe, it, beforeEach, setFixtures, expect */
+
+describe("bubblebox", function () {
+ function resetHtml() {
+ setFixtures('<ul id="bubbleBox_list"></ul><div id="bubbleBox"></div>');
+ }
+
+ var itemSelector = '.ui-bubblebox-item',
+ box, list;
+
+ beforeEach(function() {
+ resetHtml();
+ $('#bubbleBox').bubbleBox();
+ box = $('#bubbleBox');
+ list = $('#bubbleBox_list');
+ });
+
+ function addThreeItems() {
+ box.bubbleBox("addItem", "my value 1");
+ box.bubbleBox("addItem", "my value 2");
+ box.bubbleBox("addItem", "my value 3");
+ }
+
+ function numberOfItems() {
+ return $('#bubbleBox_list ' + itemSelector).length;
+ }
+
+ describe("adding items", function () {
+ var enterEvent = $.Event('keydown');
+ enterEvent.which = $.ui.keyCode.ENTER;
+
+ it("should do nothing when the input is empty", function () {
+ box.trigger(enterEvent);
+ expect(numberOfItems()).toEqual(0);
+ });
+ it("should add a new item when enter is pressed", function () {
+ box.val('my value');
+ box.trigger(enterEvent);
+ expect(numberOfItems()).toEqual(1);
+ });
+ it("should clear the input after an item is added", function () {
+ box.val('my value');
+ box.trigger(enterEvent);
+ expect(numberOfItems()).toEqual(1);
+ expect(box.val()).toEqual('');
+ });
+ it("should add a new item when comma is pressed", function () {
+ box.val('my value');
+ var commaEvent = $.Event('keydown');
+
+ commaEvent.which = $.ui.keyCode.COMMA;
+ box.trigger(commaEvent);
+ expect(numberOfItems()).toEqual(1);
+ });
+ it("should add a new item when semicolon is pressed", function () {
+ box.val('my value');
+ var semicolonEvent = $.Event('keydown');
+
+ semicolonEvent.which = 59;
+ box.trigger(semicolonEvent);
+ expect(numberOfItems()).toEqual(1);
+ });
+ it("should add a new item when input focus is lost", function () {
+ box.val('my value');
+ box.trigger($.Event('blur'));
+ expect($('#bubbleBox_list ' + itemSelector).length).toEqual(1);
+ });
+
+ describe("duplicate item handling", function () {
+ it("should not allow duplicates by default", function () {
+ addThreeItems();
+ expect(numberOfItems()).toEqual(3);
+ box.val('my value 1');
+ box.trigger(enterEvent);
+ expect(numberOfItems()).toEqual(3);
+ });
+ it("should allow duplicates when allowDupes is true", function () {
+ box.bubbleBox("option", "allowDupes", true);
+ addThreeItems();
+ expect(numberOfItems()).toEqual(3);
+ box.val('my value 1');
+ box.trigger(enterEvent);
+ expect(numberOfItems()).toEqual(4);
+ });
+ });
+
+ describe("seeding start data", function () {
+ it("should add items upon instantiation", function () {
+ resetHtml();
+ box.bubbleBox({
+ seedData: ['Trulia', 'Zillow']
+ });
+ expect(numberOfItems()).toEqual(2);
+ expect(box.bubbleBox("val").join(",")).toEqual("Trulia,Zillow");
+ });
+ });
+ });
+
+ describe("removing items", function () {
+ it("should remove items when the close button is clicked", function () {
+ addThreeItems();
+ expect(numberOfItems()).toEqual(3);
+ $('#bubbleBox_list>li>div').eq(0).click();
+ expect(numberOfItems()).toEqual(2);
+ });
+ it("should remove the last item when the delete key is pressed when the input is blank", function () {
+ var backspaceEvent = $.Event('keydown'),
+ box = $('#bubbleBox');
+ backspaceEvent.which = 8;
+
+ addThreeItems();
+ box.trigger(backspaceEvent);
+ expect(box.bubbleBox("val").join(',')).toEqual('my value 1,my value 2');
+ });
+ });
+
+ describe("events", function () {
+ describe("add events", function () {
+ var enterEvent = $.Event('keydown');
+ enterEvent.which = $.ui.keyCode.ENTER;
+
+ it("should trigger the beforeAdd event before a new item is added", function () {
+ box.val('my value');
+ var callback = jasmine.createSpy();
+
+ box.bind('bubbleboxbeforeadd', callback);
+ box.trigger(enterEvent);
+ expect(callback).toHaveBeenCalledWith(jasmine.any(Object), { value: 'my value' });
+ });
+ it("should not add an item if any of the beforeAdd handlers return false", function () {
+ box.val('my value');
+ var callback = jasmine.createSpy().andReturn(false);
+
+ box.bind('bubbleboxbeforeadd', callback);
+ box.trigger(enterEvent);
+
+ expect(callback).toHaveBeenCalledWith(jasmine.any(Object), { value: 'my value' });
+ expect(numberOfItems()).toEqual(0);
+ });
+ it("should trigger the afterAdd event after a new item is added", function () {
+ box.val('my value');
+ var callback = jasmine.createSpy();
+
+ box.bind('bubbleboxafteradd', callback);
+ box.trigger(enterEvent);
+
+ expect(callback).toHaveBeenCalledWith(jasmine.any(Object), { value: 'my value', node: jasmine.any(Object)});
+ expect(numberOfItems()).toEqual(1);
+ });
+ });
+
+ describe("remove events", function () {
+ it("should trigger the remove event when an event is removed via the delete key", function () {
+ var backspaceEvent = $.Event('keydown'),
+ callback = jasmine.createSpy();
+
+ backspaceEvent.which = 8;
+
+ box.bind('bubbleboxremove', callback);
+ addThreeItems();
+ box.trigger(backspaceEvent);
+ expect(numberOfItems()).toEqual(2);
+ expect(callback).toHaveBeenCalledWith(jasmine.any(Object), { value: 'my value 3', node: jasmine.any(Object)});
+ });
+ it("should trigger the remove event when an event is removed via the remove button", function () {
+ var callback = jasmine.createSpy();
+ box.bind('bubbleboxremove', callback);
+ addThreeItems();
+ $('#bubbleBox_list>li>div').eq(0).click();
+ expect(numberOfItems()).toEqual(2);
+ expect(callback).toHaveBeenCalledWith(jasmine.any(Object), { value: 'my value 1', node: jasmine.any(Object)});
+ });
+ });
+ });
+
+ describe("fetching the value", function () {
+ it("should return an array when the val() method is called", function () {
+ addThreeItems();
+ expect(box.bubbleBox("val").length).toEqual(3);
+ expect(box.bubbleBox("val")).toContain('my value 1');
+ expect(box.bubbleBox("val")).toContain('my value 2');
+ expect(box.bubbleBox("val")).toContain('my value 3');
+ });
+ });
+
+ describe("destroying", function () {
+ it("should empty the container upon destruction", function () {
+ addThreeItems();
+ expect(numberOfItems()).toEqual(3);
+ box.bubbleBox("destroy");
+ expect(numberOfItems()).toEqual(3);
+ });
+ });
+});
Please sign in to comment.
Something went wrong with that request. Please try again.