This commit is contained in:
Josh Johnson 2016-07-02 13:04:38 +01:00
parent 9b62089e1c
commit 712c8cf801
8 changed files with 166 additions and 18 deletions

4
.travis.yaml Normal file
View file

@ -0,0 +1,4 @@
language: node_js
node_js:
- "0.10"
script: npm run js:test

View file

@ -1,4 +1,4 @@
# Choices.js - beta
# Choices.js
A lightweight, configurable select box/text input plugin. Similar to Select2 and Selectize but without the jQuery dependency.
Coming soon.
@ -28,7 +28,7 @@ Coming soon.
duplicateItems: true,
delimiter: ',',
paste: true,
searchOptions: true,
search: true,
regexFilter: null,
placeholder: true,
placeholderValue: null,

File diff suppressed because one or more lines are too long

View file

@ -33,7 +33,7 @@ export class Choices {
duplicateItems: true,
delimiter: ',',
paste: true,
searchOptions: true,
search: true,
regexFilter: null,
placeholder: true,
placeholderValue: null,
@ -87,7 +87,7 @@ export class Choices {
this.passedElement = isType('String', element) ? document.querySelector(element) : element;
this.highlightPosition = 0;
this.canSearch = this.config.searchOptions;
this.canSearch = this.config.search;
// Assign preset items from passed object first
this.presetItems = this.config.items;
@ -548,14 +548,14 @@ export class Choices {
const hasFocusedInput = this.input === document.activeElement;
const hasActiveDropdown = this.dropdown.classList.contains(this.config.classNames.activeState);
const hasItems = this.itemList && this.itemList.children;
const keyString = String.fromCharCode(event.keyCode);
const keyString = String.fromCharCode(e.keyCode);
// If a user is typing and the dropdown is not active
if(this.passedElement.type !== 'text' && /[a-zA-Z0-9-_ ]/.test(keyString) && !hasActiveDropdown) {
this.showDropdown();
}
this.canSearch = this.config.searchOptions;
this.canSearch = this.config.search;
switch (e.keyCode) {
case aKey:
@ -1243,17 +1243,16 @@ export class Choices {
if(this.passedElement.type === 'select-multiple' || this.passedElement.type === 'text') {
containerInner.appendChild(input);
} else if(this.config.searchOptions) {
} else if(this.config.search) {
dropdown.insertBefore(input, dropdown.firstChild);
}
if(this.passedElement.type === 'select-multiple' || this.passedElement.type === 'select-one') {
this.highlightPosition = 0;
const passedGroups = Array.from(this.passedElement.getElementsByTagName('OPTGROUP'));
this.highlightPosition = 0;
this.isSearching = false;
if(passedGroups && passedGroups.length) {
passedGroups.forEach((group, index) => {
const isFirst = index === 0 ? true : false;
@ -1266,7 +1265,6 @@ export class Choices {
this._addChoice(option.selected, isDisabled, option.value, option.innerHTML);
});
}
} else if(this.passedElement.type === 'text') {
// Add any preset values seperated by delimiter
this.presetItems.forEach((item) => {
@ -1443,9 +1441,9 @@ export class Choices {
}
}
if(callback = this.config.callbackOnRender){
if(isType('Function', callback)) {
callback();
if(this.config.callbackOnRender){
if(isType('Function', this.config.callbackOnRender)) {
this.config.callbackOnRender();
} else {
console.error('callbackOnRender: Callback is not a function');
}

View file

@ -172,8 +172,8 @@
items: ['josh@joshuajohnson.co.uk', { value: 'joe@bloggs.co.uk', label: 'Joe Bloggs' } ],
});
const choices7 = new Choices('#choices-7', { Search: false }).setValue(['Set value 1', 'Set value 2']);
const choices7 = new Choices('#choices-7', { search: false }).setValue(['Set value 1', 'Set value 2']);
const choices10 = new Choices('#choices-10', {
placeholder: true,
placeholderValue: 'Pick an Strokes record'

View file

@ -35,6 +35,13 @@
"csso": "^1.7.0",
"eslint": "^2.4.0",
"fuse.js": "^2.2.0",
"jasmine-core": "^2.4.1",
"karma": "^1.1.0",
"karma-chrome-launcher": "^1.0.1",
"karma-coverage": "^1.0.0",
"karma-jasmine": "^1.0.2",
"karma-spec-reporter": "0.0.26",
"karma-webpack": "^1.7.0",
"node-sass": "^3.4.2",
"nodemon": "^1.9.1",
"opn-cli": "^3.1.0",

37
tests/karma.config.js Normal file
View file

@ -0,0 +1,37 @@
var webpack = require('karma-webpack');
module.exports = function(config) {
config.set({
frameworks: ['jasmine'],
files: [
'../tests/**/*_spec.js',
],
plugins: [webpack, 'karma-jasmine', 'karma-chrome-launcher', 'karma-coverage', 'karma-spec-reporter'],
browsers: ['Chrome'],
preprocessors: {
'**/*_spec.js': ['webpack'],
'src/**/*.js': ['webpack']
},
reporters: ['spec', 'coverage'],
coverageReporter: {
dir: '../tests/reports/coverage',
reporters: [{
type: 'html',
subdir: 'report-html'
}]
},
webpack: {
module: {
loaders: [{
test: /\.(js|jsx)$/,
exclude: /(bower_components|node_modules)/,
loader: 'babel-loader'
}],
}
},
colors: true,
webpackMiddleware: {
noInfo: true
},
});
};

102
tests/spec/choices_spec.js Normal file
View file

@ -0,0 +1,102 @@
import Choices from '../../assets/scripts/src/choices.js';
describe('Choices', function() {
beforeEach(function() {
this.input = document.createElement('input');
this.input.type = "text";
this.input.className = 'js-choices';
document.body.appendChild(this.input);
this.choices = new Choices(this.input);
});
afterEach(function() {
this.choices.destroy();
});
describe('should initialize Choices', function() {
it('should be defined', function() {
expect(this.choices).toBeDefined();
});
it('should have initalised', function() {
expect(this.choices.initialised).toBe(true);
});
it('should have a blank state', function() {
const blankState = {
items: [],
groups: [],
choices: [],
};
expect(this.choices.currentState).toEqual(blankState);
});
it('should expose public methods', function(){
expect(this.choices.init).toEqual(jasmine.any(Function));
expect(this.choices.destroy).toEqual(jasmine.any(Function));
expect(this.choices.highlightItem).toEqual(jasmine.any(Function));
expect(this.choices.unhighlightItem).toEqual(jasmine.any(Function));
expect(this.choices.highlightAll).toEqual(jasmine.any(Function));
expect(this.choices.unhighlightAll).toEqual(jasmine.any(Function));
expect(this.choices.removeItemsByValue).toEqual(jasmine.any(Function));
expect(this.choices.removeActiveItems).toEqual(jasmine.any(Function));
expect(this.choices.removeHighlightedItems).toEqual(jasmine.any(Function));
expect(this.choices.showDropdown).toEqual(jasmine.any(Function));
expect(this.choices.hideDropdown).toEqual(jasmine.any(Function));
expect(this.choices.toggleDropdown).toEqual(jasmine.any(Function));
expect(this.choices.setValue).toEqual(jasmine.any(Function));
expect(this.choices.clearValue).toEqual(jasmine.any(Function));
expect(this.choices.disable).toEqual(jasmine.any(Function));
expect(this.choices.ajax).toEqual(jasmine.any(Function));
expect(this.choices.clearInput).toEqual(jasmine.any(Function));
expect(this.choices.clearInput).toEqual(jasmine.any(Function));
});
});
describe('should create markup', function() {
it('should hide passed input', function() {
expect(this.choices.passedElement.style.display).toEqual('none');
});
it('should create an outer container', function() {
expect(this.choices.containerOuter).toEqual(jasmine.any(HTMLElement));
});
it('should create an inner container', function() {
expect(this.choices.containerInner).toEqual(jasmine.any(HTMLElement));
});
it('should create a choice list', function() {
expect(this.choices.choiceList).toEqual(jasmine.any(HTMLElement));
});
it('should create an item list', function() {
expect(this.choices.itemList).toEqual(jasmine.any(HTMLElement));
});
it('should create an input', function() {
expect(this.choices.input).toEqual(jasmine.any(HTMLElement));
});
it('should create a dropdown', function() {
expect(this.choices.dropdown).toEqual(jasmine.any(HTMLElement));
});
});
describe('should allow inputted values', function() {
it('should set value via using setValue()', function() {
this.choices.setValue(['test1', 'test2']);
expect(this.choices.currentState.items.length).toEqual(2);
});
it('should accept a user inputted value', function() {
this.choices.input.focus();
this.choices.input.value = 'test';
this.choices._onKeyDown({
target: this.choices.input,
keyCode: 13,
ctrlKey: false
});
expect(this.choices.currentState.items[0].value).toContain('test');
});
});
});