Skip to content

Instantly share code, notes, and snippets.

@akre54
Last active August 29, 2015 13:56
Show Gist options
  • Save akre54/9044892 to your computer and use it in GitHub Desktop.
Save akre54/9044892 to your computer and use it in GitHub Desktop.
Chaplin dropdown
<label>
<input class="dropdown__item__toggle" type="checkbox"></input>
{{title}}
</label>
var View = require('../base/view');
var OptionView = module.exports = View.extend({
tagName: 'li',
className: 'dropdown__item',
template: require('templates/dropdown-option'),
events: {
'change input[type="checkbox"]': 'toggleSelected'
},
listen: {
'change:selected model': 'updateState'
},
toggleSelected: function(e) {
this.model.set('selected', e.target.checked);
},
updateState: function() {
var selected = this.model.get('selected');
this.$el.toggleClass('dropdown__item--selected', selected);
this.$('dropdown__item__toggle').attr('checked', selected);
}
});
<div class="btn dropdown__toggle-button">{{title}}</div>
<div class="dropdown__menu">
<a href="" class="dropdown__clear-all">Clear All</a>
<input class="dropdown__typeahead"></input>
<ul class="dropdown__items"></ul>
</div>
var jasmine = require('./test-runner');
var $ = require('jquery'),
_ = require('underscore'),
Collection = require('../app/models/base/collection'),
Dropdown = require('../app/views/modules/dropdown');
var env = jasmine.getEnv();
describe = env.describe,
it = env.it,
expect = env.expect,
spyOn = env.spyOn,
beforeEach = env.beforeEach,
afterEach = env.afterEach;
describe('Dropdowns', function() {
var dropdown, toggleBtn, menu, clearAllBtn, typeahead;
var collection = new Collection([
{title: 'American Pie'},
{title: 'American Beauty'},
{title: 'A Great Design'},
{title: 'Bleed American'},
{title: 'Country Pie'}
]);
beforeEach(function() {
dropdown = new Dropdown({collection: collection, title: 'Americana'});
toggleBtn = dropdown.$('.dropdown__toggle-button');
menu = dropdown.$('.dropdown__menu');
clearAllBtn = dropdown.$('.dropdown__clear-all');
typeahead = dropdown.$('.dropdown__typeahead');
});
afterEach(function() {
dropdown.dispose();
});
describe('basics', function() {
it('should open on a singe click and remain open', function() {
spyOn($.fn, 'toggle');
toggleBtn.click();
expect($.fn.toggle).toHaveBeenCalled();
});
it('should close when a user clicks anywhere on the page other than the open dropdown div', function() {
toggleBtn.click();
$('body').click();
expect(menu.is(':visible')).toBe(false);
});
it('displays a title when opened and closed', function() {
expect(toggleBtn.text()).toBe('Americana');
toggleBtn.click();
expect(toggleBtn.text()).toBe('Americana');
});
});
describe('when open', function() {
describe('threshold', function() {
beforeEach(function() {
dropdown.threshold = 10;
});
it('shows a full list of all items when under a threshold', function() {
var models = collection.add(_(10).times(function(i) {
return {title: 'title ' + i};
}));
expect(collection.length).toBe(15);
expect(dropdown.visibleItems.length).toBe(10);
collection.remove(models);
});
it('shows a subset of items with an infinite scroll that fetches more items');
});
describe('selecting', function() {
var views, item1, item2, cbx1, cbx2;
beforeEach(function() {
views = _.toArray(dropdown.getItemViews());
item1 = views[0];
item2 = views[1];
cbx1 = item1.$('input[type="checkbox"]');
cbx2 = item2.$('input[type="checkbox"]');
_.each(views, function(view) {
view.model.set({selected: false});
});
});
it('allows a user to select one item', function() {
expect(item1.model.get('selected')).toBe(false);
cbx1.attr('checked', true).trigger('change');
expect(item1.model.get('selected')).toBe(true);
});
it('allows a user to select multiple items', function() {
expect(item1.model.get('selected')).toBe(false);
expect(item2.model.get('selected')).toBe(false);
cbx1.attr('checked', true).trigger('change');
cbx2.attr('checked', true).trigger('change');
expect(item1.model.get('selected')).toBe(true);
expect(item2.model.get('selected')).toBe(true);
});
it('changes the the item\'s background color when selected', function() {
cbx1.attr('checked', true).trigger('change');
expect(item1.$el.hasClass('selected')).toBe(true);
cbx1.attr('checked', false).trigger('change');
expect(item1.$el.hasClass('selected')).toBe(false);
// setting selected directly (i.e. from a previous session)
item1.model.set('selected', true);
expect(item1.$el.hasClass('selected')).toBe(true);
});
it('clears all selects when "clear all" is pressed', function() {
item1.model.set('selected', true);
item2.model.set('selected', true);
expect(_.filter(collection.pluck('selected'), _.identity)).toEqual([true, true]);
clearAllBtn.click();
expect(_.filter(collection.pluck('selected'), _.identity)).toEqual([]);
});
});
describe('filtering', function() {
it('allows a user to filter the list by typing', function() {
var visible = 0, hidden = 0;
dropdown.filterCallback = function(view, included) {
included ? visible++ : hidden++;
};
typeahead.val('Amer');
typeahead.trigger('change');
expect(visible).toBe(2);
expect(hidden).toBe(3);
var items = _.pluck(_.pluck(dropdown.visibleItems, 'attributes'), 'title');
expect(items).toEqual(['American Pie', 'American Beauty']);
});
});
});
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment