Update droplab
This commit is contained in:
parent
780a8968a5
commit
dab60475c7
1
.babelrc
1
.babelrc
|
|
@ -8,7 +8,6 @@
|
|||
"plugins": [
|
||||
["istanbul", {
|
||||
"exclude": [
|
||||
"app/assets/javascripts/droplab/**/*",
|
||||
"spec/javascripts/**/*"
|
||||
]
|
||||
}],
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
const DATA_TRIGGER = 'data-dropdown-trigger';
|
||||
const DATA_DROPDOWN = 'data-dropdown';
|
||||
const SELECTED_CLASS = 'droplab-item-selected';
|
||||
const ACTIVE_CLASS = 'droplab-item-active';
|
||||
|
||||
export {
|
||||
DATA_TRIGGER,
|
||||
DATA_DROPDOWN,
|
||||
SELECTED_CLASS,
|
||||
ACTIVE_CLASS,
|
||||
};
|
||||
|
|
@ -0,0 +1,137 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import utils from './utils';
|
||||
import { SELECTED_CLASS } from './constants';
|
||||
|
||||
var DropDown = function(list) {
|
||||
this.currentIndex = 0;
|
||||
this.hidden = true;
|
||||
this.list = typeof list === 'string' ? document.querySelector(list) : list;
|
||||
this.items = [];
|
||||
|
||||
this.eventWrapper = {};
|
||||
|
||||
this.getItems();
|
||||
this.initTemplateString();
|
||||
this.addEvents();
|
||||
|
||||
this.initialState = list.innerHTML;
|
||||
};
|
||||
|
||||
Object.assign(DropDown.prototype, {
|
||||
getItems: function() {
|
||||
this.items = [].slice.call(this.list.querySelectorAll('li'));
|
||||
return this.items;
|
||||
},
|
||||
|
||||
initTemplateString: function() {
|
||||
var items = this.items || this.getItems();
|
||||
|
||||
var templateString = '';
|
||||
if (items.length > 0) templateString = items[items.length - 1].outerHTML;
|
||||
this.templateString = templateString;
|
||||
|
||||
return this.templateString;
|
||||
},
|
||||
|
||||
clickEvent: function(e) {
|
||||
var selected = utils.closest(e.target, 'LI');
|
||||
if (!selected) return;
|
||||
|
||||
this.addSelectedClass(selected);
|
||||
|
||||
e.preventDefault();
|
||||
this.hide();
|
||||
|
||||
var listEvent = new CustomEvent('click.dl', {
|
||||
detail: {
|
||||
list: this,
|
||||
selected: selected,
|
||||
data: e.target.dataset,
|
||||
},
|
||||
});
|
||||
this.list.dispatchEvent(listEvent);
|
||||
},
|
||||
|
||||
addSelectedClass: function (selected) {
|
||||
this.removeSelectedClasses();
|
||||
selected.classList.add(SELECTED_CLASS);
|
||||
},
|
||||
|
||||
removeSelectedClasses: function () {
|
||||
const items = this.items || this.getItems();
|
||||
|
||||
items.forEach(item => item.classList.remove(SELECTED_CLASS));
|
||||
},
|
||||
|
||||
addEvents: function() {
|
||||
this.eventWrapper.clickEvent = this.clickEvent.bind(this)
|
||||
this.list.addEventListener('click', this.eventWrapper.clickEvent);
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
this.hidden ? this.show() : this.hide();
|
||||
},
|
||||
|
||||
setData: function(data) {
|
||||
this.data = data;
|
||||
this.render(data);
|
||||
},
|
||||
|
||||
addData: function(data) {
|
||||
this.data = (this.data || []).concat(data);
|
||||
this.render(this.data);
|
||||
},
|
||||
|
||||
render: function(data) {
|
||||
const children = data ? data.map(this.renderChildren.bind(this)) : [];
|
||||
const renderableList = this.list.querySelector('ul[data-dynamic]') || this.list;
|
||||
|
||||
renderableList.innerHTML = children.join('');
|
||||
},
|
||||
|
||||
renderChildren: function(data) {
|
||||
var html = utils.t(this.templateString, data);
|
||||
var template = document.createElement('div');
|
||||
|
||||
template.innerHTML = html;
|
||||
this.setImagesSrc(template);
|
||||
template.firstChild.style.display = data.droplab_hidden ? 'none' : 'block';
|
||||
|
||||
return template.firstChild.outerHTML;
|
||||
},
|
||||
|
||||
setImagesSrc: function(template) {
|
||||
const images = [].slice.call(template.querySelectorAll('img[data-src]'));
|
||||
|
||||
images.forEach((image) => {
|
||||
image.src = image.getAttribute('data-src');
|
||||
image.removeAttribute('data-src');
|
||||
});
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if (!this.hidden) return;
|
||||
this.list.style.display = 'block';
|
||||
this.currentIndex = 0;
|
||||
this.hidden = false;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (this.hidden) return;
|
||||
this.list.style.display = 'none';
|
||||
this.currentIndex = 0;
|
||||
this.hidden = true;
|
||||
},
|
||||
|
||||
toggle: function () {
|
||||
this.hidden ? this.show() : this.hide();
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.hide();
|
||||
this.list.removeEventListener('click', this.eventWrapper.clickEvent);
|
||||
}
|
||||
});
|
||||
|
||||
export default DropDown;
|
||||
|
|
@ -0,0 +1,152 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import HookButton from './hook_button';
|
||||
import HookInput from './hook_input';
|
||||
import utils from './utils';
|
||||
import Keyboard from './keyboard';
|
||||
import { DATA_TRIGGER } from './constants';
|
||||
|
||||
var DropLab = function() {
|
||||
this.ready = false;
|
||||
this.hooks = [];
|
||||
this.queuedData = [];
|
||||
this.config = {};
|
||||
|
||||
this.eventWrapper = {};
|
||||
};
|
||||
|
||||
Object.assign(DropLab.prototype, {
|
||||
loadStatic: function(){
|
||||
var dropdownTriggers = [].slice.apply(document.querySelectorAll(`[${DATA_TRIGGER}]`));
|
||||
this.addHooks(dropdownTriggers);
|
||||
},
|
||||
|
||||
addData: function () {
|
||||
var args = [].slice.apply(arguments);
|
||||
this.applyArgs(args, '_addData');
|
||||
},
|
||||
|
||||
setData: function() {
|
||||
var args = [].slice.apply(arguments);
|
||||
this.applyArgs(args, '_setData');
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.hooks.forEach(hook => hook.destroy());
|
||||
this.hooks = [];
|
||||
this.removeEvents();
|
||||
},
|
||||
|
||||
applyArgs: function(args, methodName) {
|
||||
if (this.ready) return this[methodName].apply(this, args);
|
||||
|
||||
this.queuedData = this.queuedData || [];
|
||||
this.queuedData.push(args);
|
||||
},
|
||||
|
||||
_addData: function(trigger, data) {
|
||||
this._processData(trigger, data, 'addData');
|
||||
},
|
||||
|
||||
_setData: function(trigger, data) {
|
||||
this._processData(trigger, data, 'setData');
|
||||
},
|
||||
|
||||
_processData: function(trigger, data, methodName) {
|
||||
this.hooks.forEach((hook) => {
|
||||
if (Array.isArray(trigger)) hook.list[methodName](trigger);
|
||||
|
||||
if (hook.trigger.id === trigger) hook.list[methodName](data);
|
||||
});
|
||||
},
|
||||
|
||||
addEvents: function() {
|
||||
this.eventWrapper.documentClicked = this.documentClicked.bind(this)
|
||||
document.addEventListener('click', this.eventWrapper.documentClicked);
|
||||
},
|
||||
|
||||
documentClicked: function(e) {
|
||||
let thisTag = e.target;
|
||||
|
||||
if (thisTag.tagName !== 'UL') thisTag = utils.closest(thisTag, 'UL');
|
||||
if (utils.isDropDownParts(thisTag, this.hooks) || utils.isDropDownParts(e.target, this.hooks)) return;
|
||||
|
||||
this.hooks.forEach(hook => hook.list.hide());
|
||||
},
|
||||
|
||||
removeEvents: function(){
|
||||
document.removeEventListener('click', this.eventWrapper.documentClicked);
|
||||
},
|
||||
|
||||
changeHookList: function(trigger, list, plugins, config) {
|
||||
const availableTrigger = typeof trigger === 'string' ? document.getElementById(trigger) : trigger;
|
||||
|
||||
|
||||
this.hooks.forEach((hook, i) => {
|
||||
hook.list.list.dataset.dropdownActive = false;
|
||||
|
||||
if (hook.trigger !== availableTrigger) return;
|
||||
|
||||
hook.destroy();
|
||||
this.hooks.splice(i, 1);
|
||||
this.addHook(availableTrigger, list, plugins, config);
|
||||
});
|
||||
},
|
||||
|
||||
addHook: function(hook, list, plugins, config) {
|
||||
const availableHook = typeof hook === 'string' ? document.querySelector(hook) : hook;
|
||||
let availableList;
|
||||
|
||||
if (typeof list === 'string') {
|
||||
availableList = document.querySelector(list);
|
||||
} else if (list instanceof Element) {
|
||||
availableList = list;
|
||||
} else {
|
||||
availableList = document.querySelector(hook.dataset[utils.toCamelCase(DATA_TRIGGER)]);
|
||||
}
|
||||
|
||||
availableList.dataset.dropdownActive = true;
|
||||
|
||||
const HookObject = availableHook.tagName === 'INPUT' ? HookInput : HookButton;
|
||||
this.hooks.push(new HookObject(availableHook, availableList, plugins, config));
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
addHooks: function(hooks, plugins, config) {
|
||||
hooks.forEach(hook => this.addHook(hook, null, plugins, config));
|
||||
return this;
|
||||
},
|
||||
|
||||
setConfig: function(obj){
|
||||
this.config = obj;
|
||||
},
|
||||
|
||||
fireReady: function() {
|
||||
const readyEvent = new CustomEvent('ready.dl', {
|
||||
detail: {
|
||||
dropdown: this,
|
||||
},
|
||||
});
|
||||
document.dispatchEvent(readyEvent);
|
||||
|
||||
this.ready = true;
|
||||
},
|
||||
|
||||
init: function (hook, list, plugins, config) {
|
||||
hook ? this.addHook(hook, list, plugins, config) : this.loadStatic();
|
||||
|
||||
this.addEvents();
|
||||
|
||||
Keyboard();
|
||||
|
||||
this.fireReady();
|
||||
|
||||
this.queuedData.forEach(data => this.addData(data));
|
||||
this.queuedData = [];
|
||||
|
||||
return this;
|
||||
},
|
||||
});
|
||||
|
||||
export default DropLab;
|
||||
|
|
@ -1,741 +0,0 @@
|
|||
/* eslint-disable */
|
||||
// Determine where to place this
|
||||
if (typeof Object.assign != 'function') {
|
||||
Object.assign = function (target, varArgs) { // .length of function is 2
|
||||
'use strict';
|
||||
if (target == null) { // TypeError if undefined or null
|
||||
throw new TypeError('Cannot convert undefined or null to object');
|
||||
}
|
||||
|
||||
var to = Object(target);
|
||||
|
||||
for (var index = 1; index < arguments.length; index++) {
|
||||
var nextSource = arguments[index];
|
||||
|
||||
if (nextSource != null) { // Skip over if undefined or null
|
||||
for (var nextKey in nextSource) {
|
||||
// Avoid bugs when hasOwnProperty is shadowed
|
||||
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
|
||||
to[nextKey] = nextSource[nextKey];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return to;
|
||||
};
|
||||
}
|
||||
|
||||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.droplab = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
var DATA_TRIGGER = 'data-dropdown-trigger';
|
||||
var DATA_DROPDOWN = 'data-dropdown';
|
||||
|
||||
module.exports = {
|
||||
DATA_TRIGGER: DATA_TRIGGER,
|
||||
DATA_DROPDOWN: DATA_DROPDOWN,
|
||||
}
|
||||
|
||||
},{}],2:[function(require,module,exports){
|
||||
// Custom event support for IE
|
||||
if ( typeof CustomEvent === "function" ) {
|
||||
module.exports = CustomEvent;
|
||||
} else {
|
||||
require('./window')(function(w){
|
||||
var CustomEvent = function ( event, params ) {
|
||||
params = params || { bubbles: false, cancelable: false, detail: undefined };
|
||||
var evt = document.createEvent( 'CustomEvent' );
|
||||
evt.initCustomEvent( event, params.bubbles, params.cancelable, params.detail );
|
||||
return evt;
|
||||
}
|
||||
CustomEvent.prototype = w.Event.prototype;
|
||||
|
||||
w.CustomEvent = CustomEvent;
|
||||
});
|
||||
module.exports = CustomEvent;
|
||||
}
|
||||
|
||||
},{"./window":11}],3:[function(require,module,exports){
|
||||
var CustomEvent = require('./custom_event_polyfill');
|
||||
var utils = require('./utils');
|
||||
|
||||
var DropDown = function(list) {
|
||||
this.currentIndex = 0;
|
||||
this.hidden = true;
|
||||
this.list = list;
|
||||
this.items = [];
|
||||
this.getItems();
|
||||
this.initTemplateString();
|
||||
this.addEvents();
|
||||
this.initialState = list.innerHTML;
|
||||
};
|
||||
|
||||
Object.assign(DropDown.prototype, {
|
||||
getItems: function() {
|
||||
this.items = [].slice.call(this.list.querySelectorAll('li'));
|
||||
return this.items;
|
||||
},
|
||||
|
||||
initTemplateString: function() {
|
||||
var items = this.items || this.getItems();
|
||||
|
||||
var templateString = '';
|
||||
if(items.length > 0) {
|
||||
templateString = items[items.length - 1].outerHTML;
|
||||
}
|
||||
this.templateString = templateString;
|
||||
return this.templateString;
|
||||
},
|
||||
|
||||
clickEvent: function(e) {
|
||||
// climb up the tree to find the LI
|
||||
var selected = utils.closest(e.target, 'LI');
|
||||
|
||||
if(selected) {
|
||||
e.preventDefault();
|
||||
this.hide();
|
||||
var listEvent = new CustomEvent('click.dl', {
|
||||
detail: {
|
||||
list: this,
|
||||
selected: selected,
|
||||
data: e.target.dataset,
|
||||
},
|
||||
});
|
||||
this.list.dispatchEvent(listEvent);
|
||||
}
|
||||
},
|
||||
|
||||
addEvents: function() {
|
||||
this.clickWrapper = this.clickEvent.bind(this);
|
||||
// event delegation.
|
||||
this.list.addEventListener('click', this.clickWrapper);
|
||||
},
|
||||
|
||||
toggle: function() {
|
||||
if(this.hidden) {
|
||||
this.show();
|
||||
} else {
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
setData: function(data) {
|
||||
this.data = data;
|
||||
this.render(data);
|
||||
},
|
||||
|
||||
addData: function(data) {
|
||||
this.data = (this.data || []).concat(data);
|
||||
this.render(this.data);
|
||||
},
|
||||
|
||||
// call render manually on data;
|
||||
render: function(data){
|
||||
// debugger
|
||||
// empty the list first
|
||||
var templateString = this.templateString;
|
||||
var newChildren = [];
|
||||
var toAppend;
|
||||
|
||||
newChildren = (data ||[]).map(function(dat){
|
||||
var html = utils.t(templateString, dat);
|
||||
var template = document.createElement('div');
|
||||
template.innerHTML = html;
|
||||
|
||||
// Help set the image src template
|
||||
var imageTags = template.querySelectorAll('img[data-src]');
|
||||
// debugger
|
||||
for(var i = 0; i < imageTags.length; i++) {
|
||||
var imageTag = imageTags[i];
|
||||
imageTag.src = imageTag.getAttribute('data-src');
|
||||
imageTag.removeAttribute('data-src');
|
||||
}
|
||||
|
||||
if(dat.hasOwnProperty('droplab_hidden') && dat.droplab_hidden){
|
||||
template.firstChild.style.display = 'none'
|
||||
}else{
|
||||
template.firstChild.style.display = 'block';
|
||||
}
|
||||
return template.firstChild.outerHTML;
|
||||
});
|
||||
toAppend = this.list.querySelector('ul[data-dynamic]');
|
||||
if(toAppend) {
|
||||
toAppend.innerHTML = newChildren.join('');
|
||||
} else {
|
||||
this.list.innerHTML = newChildren.join('');
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
if (this.hidden) {
|
||||
// debugger
|
||||
this.list.style.display = 'block';
|
||||
this.currentIndex = 0;
|
||||
this.hidden = false;
|
||||
}
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
if (!this.hidden) {
|
||||
// debugger
|
||||
this.list.style.display = 'none';
|
||||
this.currentIndex = 0;
|
||||
this.hidden = true;
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.hide();
|
||||
this.list.removeEventListener('click', this.clickWrapper);
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = DropDown;
|
||||
|
||||
},{"./custom_event_polyfill":2,"./utils":10}],4:[function(require,module,exports){
|
||||
require('./window')(function(w){
|
||||
module.exports = function(deps) {
|
||||
deps = deps || {};
|
||||
var window = deps.window || w;
|
||||
var document = deps.document || window.document;
|
||||
var CustomEvent = deps.CustomEvent || require('./custom_event_polyfill');
|
||||
var HookButton = deps.HookButton || require('./hook_button');
|
||||
var HookInput = deps.HookInput || require('./hook_input');
|
||||
var utils = deps.utils || require('./utils');
|
||||
var DATA_TRIGGER = require('./constants').DATA_TRIGGER;
|
||||
|
||||
var DropLab = function(hook){
|
||||
if (!(this instanceof DropLab)) return new DropLab(hook);
|
||||
this.ready = false;
|
||||
this.hooks = [];
|
||||
this.queuedData = [];
|
||||
this.config = {};
|
||||
this.loadWrapper;
|
||||
if(typeof hook !== 'undefined'){
|
||||
this.addHook(hook);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
Object.assign(DropLab.prototype, {
|
||||
load: function() {
|
||||
this.loadWrapper();
|
||||
},
|
||||
|
||||
loadWrapper: function(){
|
||||
var dropdownTriggers = [].slice.apply(document.querySelectorAll('['+DATA_TRIGGER+']'));
|
||||
this.addHooks(dropdownTriggers).init();
|
||||
},
|
||||
|
||||
addData: function () {
|
||||
var args = [].slice.apply(arguments);
|
||||
this.applyArgs(args, '_addData');
|
||||
},
|
||||
|
||||
setData: function() {
|
||||
var args = [].slice.apply(arguments);
|
||||
this.applyArgs(args, '_setData');
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
for(var i = 0; i < this.hooks.length; i++) {
|
||||
this.hooks[i].destroy();
|
||||
}
|
||||
this.hooks = [];
|
||||
this.removeEvents();
|
||||
},
|
||||
|
||||
applyArgs: function(args, methodName) {
|
||||
if(this.ready) {
|
||||
this[methodName].apply(this, args);
|
||||
} else {
|
||||
this.queuedData = this.queuedData || [];
|
||||
this.queuedData.push(args);
|
||||
}
|
||||
},
|
||||
|
||||
_addData: function(trigger, data) {
|
||||
this._processData(trigger, data, 'addData');
|
||||
},
|
||||
|
||||
_setData: function(trigger, data) {
|
||||
this._processData(trigger, data, 'setData');
|
||||
},
|
||||
|
||||
_processData: function(trigger, data, methodName) {
|
||||
for(var i = 0; i < this.hooks.length; i++) {
|
||||
var hook = this.hooks[i];
|
||||
if(hook.trigger.dataset.hasOwnProperty('id')) {
|
||||
if(hook.trigger.dataset.id === trigger) {
|
||||
hook.list[methodName](data);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
addEvents: function() {
|
||||
var self = this;
|
||||
this.windowClickedWrapper = function(e){
|
||||
var thisTag = e.target;
|
||||
if(thisTag.tagName !== 'UL'){
|
||||
// climb up the tree to find the UL
|
||||
thisTag = utils.closest(thisTag, 'UL');
|
||||
}
|
||||
if(utils.isDropDownParts(thisTag)){ return }
|
||||
if(utils.isDropDownParts(e.target)){ return }
|
||||
for(var i = 0; i < self.hooks.length; i++) {
|
||||
self.hooks[i].list.hide();
|
||||
}
|
||||
}.bind(this);
|
||||
document.addEventListener('click', this.windowClickedWrapper);
|
||||
},
|
||||
|
||||
removeEvents: function(){
|
||||
w.removeEventListener('click', this.windowClickedWrapper);
|
||||
w.removeEventListener('load', this.loadWrapper);
|
||||
},
|
||||
|
||||
changeHookList: function(trigger, list, plugins, config) {
|
||||
trigger = document.querySelector('[data-id="'+trigger+'"]');
|
||||
// list = document.querySelector(list);
|
||||
this.hooks.every(function(hook, i) {
|
||||
if(hook.trigger === trigger) {
|
||||
hook.destroy();
|
||||
this.hooks.splice(i, 1);
|
||||
this.addHook(trigger, list, plugins, config);
|
||||
return false;
|
||||
}
|
||||
return true
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
addHook: function(hook, list, plugins, config) {
|
||||
if(!(hook instanceof HTMLElement) && typeof hook === 'string'){
|
||||
hook = document.querySelector(hook);
|
||||
}
|
||||
if(!list){
|
||||
list = document.querySelector(hook.dataset[utils.toDataCamelCase(DATA_TRIGGER)]);
|
||||
}
|
||||
|
||||
if(hook) {
|
||||
if(hook.tagName === 'A' || hook.tagName === 'BUTTON') {
|
||||
this.hooks.push(new HookButton(hook, list, plugins, config));
|
||||
} else if(hook.tagName === 'INPUT') {
|
||||
this.hooks.push(new HookInput(hook, list, plugins, config));
|
||||
}
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
addHooks: function(hooks, plugins, config) {
|
||||
for(var i = 0; i < hooks.length; i++) {
|
||||
var hook = hooks[i];
|
||||
this.addHook(hook, null, plugins, config);
|
||||
}
|
||||
return this;
|
||||
},
|
||||
|
||||
setConfig: function(obj){
|
||||
this.config = obj;
|
||||
},
|
||||
|
||||
init: function () {
|
||||
this.addEvents();
|
||||
var readyEvent = new CustomEvent('ready.dl', {
|
||||
detail: {
|
||||
dropdown: this,
|
||||
},
|
||||
});
|
||||
window.dispatchEvent(readyEvent);
|
||||
this.ready = true;
|
||||
for(var i = 0; i < this.queuedData.length; i++) {
|
||||
this.addData.apply(this, this.queuedData[i]);
|
||||
}
|
||||
this.queuedData = [];
|
||||
return this;
|
||||
},
|
||||
});
|
||||
|
||||
return DropLab;
|
||||
};
|
||||
});
|
||||
|
||||
},{"./constants":1,"./custom_event_polyfill":2,"./hook_button":6,"./hook_input":7,"./utils":10,"./window":11}],5:[function(require,module,exports){
|
||||
var DropDown = require('./dropdown');
|
||||
|
||||
var Hook = function(trigger, list, plugins, config){
|
||||
this.trigger = trigger;
|
||||
this.list = new DropDown(list);
|
||||
this.type = 'Hook';
|
||||
this.event = 'click';
|
||||
this.plugins = plugins || [];
|
||||
this.config = config || {};
|
||||
this.id = trigger.dataset.id;
|
||||
};
|
||||
|
||||
Object.assign(Hook.prototype, {
|
||||
|
||||
addEvents: function(){},
|
||||
|
||||
constructor: Hook,
|
||||
});
|
||||
|
||||
module.exports = Hook;
|
||||
|
||||
},{"./dropdown":3}],6:[function(require,module,exports){
|
||||
var CustomEvent = require('./custom_event_polyfill');
|
||||
var Hook = require('./hook');
|
||||
|
||||
var HookButton = function(trigger, list, plugins, config) {
|
||||
Hook.call(this, trigger, list, plugins, config);
|
||||
this.type = 'button';
|
||||
this.event = 'click';
|
||||
this.addEvents();
|
||||
this.addPlugins();
|
||||
};
|
||||
|
||||
HookButton.prototype = Object.create(Hook.prototype);
|
||||
|
||||
Object.assign(HookButton.prototype, {
|
||||
addPlugins: function() {
|
||||
for(var i = 0; i < this.plugins.length; i++) {
|
||||
this.plugins[i].init(this);
|
||||
}
|
||||
},
|
||||
|
||||
clicked: function(e){
|
||||
var buttonEvent = new CustomEvent('click.dl', {
|
||||
detail: {
|
||||
hook: this,
|
||||
},
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
this.list.show();
|
||||
e.target.dispatchEvent(buttonEvent);
|
||||
},
|
||||
|
||||
addEvents: function(){
|
||||
this.clickedWrapper = this.clicked.bind(this);
|
||||
this.trigger.addEventListener('click', this.clickedWrapper);
|
||||
},
|
||||
|
||||
removeEvents: function(){
|
||||
this.trigger.removeEventListener('click', this.clickedWrapper);
|
||||
},
|
||||
|
||||
restoreInitialState: function() {
|
||||
this.list.list.innerHTML = this.list.initialState;
|
||||
},
|
||||
|
||||
removePlugins: function() {
|
||||
for(var i = 0; i < this.plugins.length; i++) {
|
||||
this.plugins[i].destroy();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.restoreInitialState();
|
||||
this.removeEvents();
|
||||
this.removePlugins();
|
||||
},
|
||||
|
||||
|
||||
constructor: HookButton,
|
||||
});
|
||||
|
||||
|
||||
module.exports = HookButton;
|
||||
|
||||
},{"./custom_event_polyfill":2,"./hook":5}],7:[function(require,module,exports){
|
||||
var CustomEvent = require('./custom_event_polyfill');
|
||||
var Hook = require('./hook');
|
||||
|
||||
var HookInput = function(trigger, list, plugins, config) {
|
||||
Hook.call(this, trigger, list, plugins, config);
|
||||
this.type = 'input';
|
||||
this.event = 'input';
|
||||
this.addPlugins();
|
||||
this.addEvents();
|
||||
};
|
||||
|
||||
Object.assign(HookInput.prototype, {
|
||||
addPlugins: function() {
|
||||
var self = this;
|
||||
for(var i = 0; i < this.plugins.length; i++) {
|
||||
this.plugins[i].init(self);
|
||||
}
|
||||
},
|
||||
|
||||
addEvents: function(){
|
||||
var self = this;
|
||||
|
||||
this.mousedown = function mousedown(e) {
|
||||
if(self.hasRemovedEvents) return;
|
||||
|
||||
var mouseEvent = new CustomEvent('mousedown.dl', {
|
||||
detail: {
|
||||
hook: self,
|
||||
text: e.target.value,
|
||||
},
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
e.target.dispatchEvent(mouseEvent);
|
||||
}
|
||||
|
||||
this.input = function input(e) {
|
||||
if(self.hasRemovedEvents) return;
|
||||
|
||||
self.list.show();
|
||||
|
||||
var inputEvent = new CustomEvent('input.dl', {
|
||||
detail: {
|
||||
hook: self,
|
||||
text: e.target.value,
|
||||
},
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
e.target.dispatchEvent(inputEvent);
|
||||
}
|
||||
|
||||
this.keyup = function keyup(e) {
|
||||
if(self.hasRemovedEvents) return;
|
||||
|
||||
keyEvent(e, 'keyup.dl');
|
||||
}
|
||||
|
||||
this.keydown = function keydown(e) {
|
||||
if(self.hasRemovedEvents) return;
|
||||
|
||||
keyEvent(e, 'keydown.dl');
|
||||
}
|
||||
|
||||
function keyEvent(e, keyEventName){
|
||||
self.list.show();
|
||||
|
||||
var keyEvent = new CustomEvent(keyEventName, {
|
||||
detail: {
|
||||
hook: self,
|
||||
text: e.target.value,
|
||||
which: e.which,
|
||||
key: e.key,
|
||||
},
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
e.target.dispatchEvent(keyEvent);
|
||||
}
|
||||
|
||||
this.events = this.events || {};
|
||||
this.events.mousedown = this.mousedown;
|
||||
this.events.input = this.input;
|
||||
this.events.keyup = this.keyup;
|
||||
this.events.keydown = this.keydown;
|
||||
this.trigger.addEventListener('mousedown', this.mousedown);
|
||||
this.trigger.addEventListener('input', this.input);
|
||||
this.trigger.addEventListener('keyup', this.keyup);
|
||||
this.trigger.addEventListener('keydown', this.keydown);
|
||||
},
|
||||
|
||||
removeEvents: function() {
|
||||
this.hasRemovedEvents = true;
|
||||
this.trigger.removeEventListener('mousedown', this.mousedown);
|
||||
this.trigger.removeEventListener('input', this.input);
|
||||
this.trigger.removeEventListener('keyup', this.keyup);
|
||||
this.trigger.removeEventListener('keydown', this.keydown);
|
||||
},
|
||||
|
||||
restoreInitialState: function() {
|
||||
this.list.list.innerHTML = this.list.initialState;
|
||||
},
|
||||
|
||||
removePlugins: function() {
|
||||
for(var i = 0; i < this.plugins.length; i++) {
|
||||
this.plugins[i].destroy();
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.restoreInitialState();
|
||||
this.removeEvents();
|
||||
this.removePlugins();
|
||||
this.list.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
module.exports = HookInput;
|
||||
|
||||
},{"./custom_event_polyfill":2,"./hook":5}],8:[function(require,module,exports){
|
||||
var DropLab = require('./droplab')();
|
||||
var DATA_TRIGGER = require('./constants').DATA_TRIGGER;
|
||||
var keyboard = require('./keyboard')();
|
||||
var setup = function() {
|
||||
window.DropLab = DropLab;
|
||||
};
|
||||
|
||||
|
||||
module.exports = setup();
|
||||
|
||||
},{"./constants":1,"./droplab":4,"./keyboard":9}],9:[function(require,module,exports){
|
||||
require('./window')(function(w){
|
||||
module.exports = function(){
|
||||
var currentKey;
|
||||
var currentFocus;
|
||||
var isUpArrow = false;
|
||||
var isDownArrow = false;
|
||||
var removeHighlight = function removeHighlight(list) {
|
||||
var listItems = Array.prototype.slice.call(list.list.querySelectorAll('li:not(.divider)'), 0);
|
||||
var listItemsTmp = [];
|
||||
for(var i = 0; i < listItems.length; i++) {
|
||||
var listItem = listItems[i];
|
||||
listItem.classList.remove('dropdown-active');
|
||||
|
||||
if (listItem.style.display !== 'none') {
|
||||
listItemsTmp.push(listItem);
|
||||
}
|
||||
}
|
||||
return listItemsTmp;
|
||||
};
|
||||
|
||||
var setMenuForArrows = function setMenuForArrows(list) {
|
||||
var listItems = removeHighlight(list);
|
||||
if(list.currentIndex>0){
|
||||
if(!listItems[list.currentIndex-1]){
|
||||
list.currentIndex = list.currentIndex-1;
|
||||
}
|
||||
|
||||
if (listItems[list.currentIndex-1]) {
|
||||
var el = listItems[list.currentIndex-1];
|
||||
var filterDropdownEl = el.closest('.filter-dropdown');
|
||||
el.classList.add('dropdown-active');
|
||||
|
||||
if (filterDropdownEl) {
|
||||
var filterDropdownBottom = filterDropdownEl.offsetHeight;
|
||||
var elOffsetTop = el.offsetTop - 30;
|
||||
|
||||
if (elOffsetTop > filterDropdownBottom) {
|
||||
filterDropdownEl.scrollTop = elOffsetTop - filterDropdownBottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var mousedown = function mousedown(e) {
|
||||
var list = e.detail.hook.list;
|
||||
removeHighlight(list);
|
||||
list.show();
|
||||
list.currentIndex = 0;
|
||||
isUpArrow = false;
|
||||
isDownArrow = false;
|
||||
};
|
||||
var selectItem = function selectItem(list) {
|
||||
var listItems = removeHighlight(list);
|
||||
var currentItem = listItems[list.currentIndex-1];
|
||||
var listEvent = new CustomEvent('click.dl', {
|
||||
detail: {
|
||||
list: list,
|
||||
selected: currentItem,
|
||||
data: currentItem.dataset,
|
||||
},
|
||||
});
|
||||
list.list.dispatchEvent(listEvent);
|
||||
list.hide();
|
||||
}
|
||||
|
||||
var keydown = function keydown(e){
|
||||
var typedOn = e.target;
|
||||
var list = e.detail.hook.list;
|
||||
var currentIndex = list.currentIndex;
|
||||
isUpArrow = false;
|
||||
isDownArrow = false;
|
||||
|
||||
if(e.detail.which){
|
||||
currentKey = e.detail.which;
|
||||
if(currentKey === 13){
|
||||
selectItem(e.detail.hook.list);
|
||||
return;
|
||||
}
|
||||
if(currentKey === 38) {
|
||||
isUpArrow = true;
|
||||
}
|
||||
if(currentKey === 40) {
|
||||
isDownArrow = true;
|
||||
}
|
||||
} else if(e.detail.key) {
|
||||
currentKey = e.detail.key;
|
||||
if(currentKey === 'Enter'){
|
||||
selectItem(e.detail.hook.list);
|
||||
return;
|
||||
}
|
||||
if(currentKey === 'ArrowUp') {
|
||||
isUpArrow = true;
|
||||
}
|
||||
if(currentKey === 'ArrowDown') {
|
||||
isDownArrow = true;
|
||||
}
|
||||
}
|
||||
if(isUpArrow){ currentIndex--; }
|
||||
if(isDownArrow){ currentIndex++; }
|
||||
if(currentIndex < 0){ currentIndex = 0; }
|
||||
list.currentIndex = currentIndex;
|
||||
setMenuForArrows(e.detail.hook.list);
|
||||
};
|
||||
|
||||
w.addEventListener('mousedown.dl', mousedown);
|
||||
w.addEventListener('keydown.dl', keydown);
|
||||
};
|
||||
});
|
||||
},{"./window":11}],10:[function(require,module,exports){
|
||||
var DATA_TRIGGER = require('./constants').DATA_TRIGGER;
|
||||
var DATA_DROPDOWN = require('./constants').DATA_DROPDOWN;
|
||||
|
||||
var toDataCamelCase = function(attr){
|
||||
return this.camelize(attr.split('-').slice(1).join(' '));
|
||||
};
|
||||
|
||||
// the tiniest damn templating I can do
|
||||
var t = function(s,d){
|
||||
for(var p in d)
|
||||
s=s.replace(new RegExp('{{'+p+'}}','g'), d[p]);
|
||||
return s;
|
||||
};
|
||||
|
||||
var camelize = function(str) {
|
||||
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, function(letter, index) {
|
||||
return index == 0 ? letter.toLowerCase() : letter.toUpperCase();
|
||||
}).replace(/\s+/g, '');
|
||||
};
|
||||
|
||||
var closest = function(thisTag, stopTag) {
|
||||
while(thisTag && thisTag.tagName !== stopTag && thisTag.tagName !== 'HTML'){
|
||||
thisTag = thisTag.parentNode;
|
||||
}
|
||||
return thisTag;
|
||||
};
|
||||
|
||||
var isDropDownParts = function(target) {
|
||||
if(!target || target.tagName === 'HTML') { return false; }
|
||||
return (
|
||||
target.hasAttribute(DATA_TRIGGER) ||
|
||||
target.hasAttribute(DATA_DROPDOWN)
|
||||
);
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
toDataCamelCase: toDataCamelCase,
|
||||
t: t,
|
||||
camelize: camelize,
|
||||
closest: closest,
|
||||
isDropDownParts: isDropDownParts,
|
||||
};
|
||||
|
||||
},{"./constants":1}],11:[function(require,module,exports){
|
||||
module.exports = function(callback) {
|
||||
return (function() {
|
||||
callback(this);
|
||||
}).call(null);
|
||||
};
|
||||
|
||||
},{}]},{},[8])(8)
|
||||
});
|
||||
|
|
@ -1,103 +0,0 @@
|
|||
/* eslint-disable */
|
||||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g=(g.droplab||(g.droplab = {}));g=(g.ajax||(g.ajax = {}));g=(g.datasource||(g.datasource = {}));g.js = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
/* global droplab */
|
||||
|
||||
require('../window')(function(w){
|
||||
function droplabAjaxException(message) {
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
w.droplabAjax = {
|
||||
_loadUrlData: function _loadUrlData(url) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open('GET', url, true);
|
||||
xhr.onreadystatechange = function () {
|
||||
if(xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
self.cache[url] = data;
|
||||
return resolve(data);
|
||||
} else {
|
||||
return reject([xhr.responseText, xhr.status]);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
},
|
||||
|
||||
_loadData: function _loadData(data, config, self) {
|
||||
if (config.loadingTemplate) {
|
||||
var dataLoadingTemplate = self.hook.list.list.querySelector('[data-loading-template]');
|
||||
|
||||
if (dataLoadingTemplate) {
|
||||
dataLoadingTemplate.outerHTML = self.listTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.destroyed) {
|
||||
self.hook.list[config.method].call(self.hook.list, data);
|
||||
}
|
||||
},
|
||||
|
||||
init: function init(hook) {
|
||||
var self = this;
|
||||
self.destroyed = false;
|
||||
self.cache = self.cache || {};
|
||||
var config = hook.config.droplabAjax;
|
||||
this.hook = hook;
|
||||
|
||||
if (!config || !config.endpoint || !config.method) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.method !== 'setData' && config.method !== 'addData') {
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.loadingTemplate) {
|
||||
var dynamicList = hook.list.list.querySelector('[data-dynamic]');
|
||||
|
||||
var loadingTemplate = document.createElement('div');
|
||||
loadingTemplate.innerHTML = config.loadingTemplate;
|
||||
loadingTemplate.setAttribute('data-loading-template', '');
|
||||
|
||||
this.listTemplate = dynamicList.outerHTML;
|
||||
dynamicList.outerHTML = loadingTemplate.outerHTML;
|
||||
}
|
||||
|
||||
if (self.cache[config.endpoint]) {
|
||||
self._loadData(self.cache[config.endpoint], config, self);
|
||||
} else {
|
||||
this._loadUrlData(config.endpoint)
|
||||
.then(function(d) {
|
||||
self._loadData(d, config, self);
|
||||
}, function(xhrError) {
|
||||
// TODO: properly handle errors due to XHR cancellation
|
||||
return;
|
||||
}).catch(function(e) {
|
||||
throw new droplabAjaxException(e.message || e);
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
var dynamicList = this.hook.list.list.querySelector('[data-dynamic]');
|
||||
this.destroyed = true;
|
||||
if (this.listTemplate && dynamicList) {
|
||||
dynamicList.outerHTML = this.listTemplate;
|
||||
}
|
||||
}
|
||||
};
|
||||
});
|
||||
},{"../window":2}],2:[function(require,module,exports){
|
||||
module.exports = function(callback) {
|
||||
return (function() {
|
||||
callback(this);
|
||||
}).call(null);
|
||||
};
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
|
|
@ -1,164 +0,0 @@
|
|||
/* eslint-disable */
|
||||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g=(g.droplab||(g.droplab = {}));g=(g.ajax||(g.ajax = {}));g=(g.datasource||(g.datasource = {}));g.js = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
/* global droplab */
|
||||
|
||||
require('../window')(function(w){
|
||||
w.droplabAjaxFilter = {
|
||||
init: function(hook) {
|
||||
this.destroyed = false;
|
||||
this.hook = hook;
|
||||
this.notLoading();
|
||||
|
||||
this.debounceTriggerWrapper = this.debounceTrigger.bind(this);
|
||||
this.hook.trigger.addEventListener('keydown.dl', this.debounceTriggerWrapper);
|
||||
this.hook.trigger.addEventListener('focus', this.debounceTriggerWrapper);
|
||||
this.trigger(true);
|
||||
},
|
||||
|
||||
notLoading: function notLoading() {
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
debounceTrigger: function debounceTrigger(e) {
|
||||
var NON_CHARACTER_KEYS = [16, 17, 18, 20, 37, 38, 39, 40, 91, 93];
|
||||
var invalidKeyPressed = NON_CHARACTER_KEYS.indexOf(e.detail.which || e.detail.keyCode) > -1;
|
||||
var focusEvent = e.type === 'focus';
|
||||
|
||||
if (invalidKeyPressed || this.loading) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
this.timeout = setTimeout(this.trigger.bind(this, focusEvent), 200);
|
||||
},
|
||||
|
||||
trigger: function trigger(getEntireList) {
|
||||
var config = this.hook.config.droplabAjaxFilter;
|
||||
var searchValue = this.trigger.value;
|
||||
|
||||
if (!config || !config.endpoint || !config.searchKey) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (config.searchValueFunction) {
|
||||
searchValue = config.searchValueFunction();
|
||||
}
|
||||
|
||||
if (config.loadingTemplate && this.hook.list.data === undefined ||
|
||||
this.hook.list.data.length === 0) {
|
||||
var dynamicList = this.hook.list.list.querySelector('[data-dynamic]');
|
||||
|
||||
var loadingTemplate = document.createElement('div');
|
||||
loadingTemplate.innerHTML = config.loadingTemplate;
|
||||
loadingTemplate.setAttribute('data-loading-template', true);
|
||||
|
||||
this.listTemplate = dynamicList.outerHTML;
|
||||
dynamicList.outerHTML = loadingTemplate.outerHTML;
|
||||
}
|
||||
|
||||
if (getEntireList) {
|
||||
searchValue = '';
|
||||
}
|
||||
|
||||
if (config.searchKey === searchValue) {
|
||||
return this.list.show();
|
||||
}
|
||||
|
||||
this.loading = true;
|
||||
|
||||
var params = config.params || {};
|
||||
params[config.searchKey] = searchValue;
|
||||
var self = this;
|
||||
self.cache = self.cache || {};
|
||||
var url = config.endpoint + this.buildParams(params);
|
||||
var urlCachedData = self.cache[url];
|
||||
|
||||
if (urlCachedData) {
|
||||
self._loadData(urlCachedData, config, self);
|
||||
} else {
|
||||
this._loadUrlData(url)
|
||||
.then(function(data) {
|
||||
self._loadData(data, config, self);
|
||||
}, function(xhrError) {
|
||||
// TODO: properly handle errors due to XHR cancellation
|
||||
return;
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
_loadUrlData: function _loadUrlData(url) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open('GET', url, true);
|
||||
xhr.onreadystatechange = function () {
|
||||
if(xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
self.cache[url] = data;
|
||||
return resolve(data);
|
||||
} else {
|
||||
return reject([xhr.responseText, xhr.status]);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
},
|
||||
|
||||
_loadData: function _loadData(data, config, self) {
|
||||
if (config.loadingTemplate && self.hook.list.data === undefined ||
|
||||
self.hook.list.data.length === 0) {
|
||||
const dataLoadingTemplate = self.hook.list.list.querySelector('[data-loading-template]');
|
||||
|
||||
if (dataLoadingTemplate) {
|
||||
dataLoadingTemplate.outerHTML = self.listTemplate;
|
||||
}
|
||||
}
|
||||
|
||||
if (!self.destroyed) {
|
||||
var hookListChildren = self.hook.list.list.children;
|
||||
var onlyDynamicList = hookListChildren.length === 1 && hookListChildren[0].hasAttribute('data-dynamic');
|
||||
|
||||
if (onlyDynamicList && data.length === 0) {
|
||||
self.hook.list.hide();
|
||||
}
|
||||
|
||||
self.hook.list.setData.call(self.hook.list, data);
|
||||
}
|
||||
self.notLoading();
|
||||
self.hook.list.currentIndex = 0;
|
||||
},
|
||||
|
||||
buildParams: function(params) {
|
||||
if (!params) return '';
|
||||
var paramsArray = Object.keys(params).map(function(param) {
|
||||
return param + '=' + (params[param] || '');
|
||||
});
|
||||
return '?' + paramsArray.join('&');
|
||||
},
|
||||
|
||||
destroy: function destroy() {
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
|
||||
this.destroyed = true;
|
||||
|
||||
this.hook.trigger.removeEventListener('keydown.dl', this.debounceTriggerWrapper);
|
||||
this.hook.trigger.removeEventListener('focus', this.debounceTriggerWrapper);
|
||||
}
|
||||
};
|
||||
});
|
||||
},{"../window":2}],2:[function(require,module,exports){
|
||||
module.exports = function(callback) {
|
||||
return (function() {
|
||||
callback(this);
|
||||
}).call(null);
|
||||
};
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
|
|
@ -1,76 +0,0 @@
|
|||
/* eslint-disable */
|
||||
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g=(g.droplab||(g.droplab = {}));g=(g.filter||(g.filter = {}));g.js = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
|
||||
/* global droplab */
|
||||
|
||||
require('../window')(function(w){
|
||||
w.droplabFilter = {
|
||||
|
||||
keydownWrapper: function(e){
|
||||
var hiddenCount = 0;
|
||||
var dataHiddenCount = 0;
|
||||
var list = e.detail.hook.list;
|
||||
var data = list.data;
|
||||
var value = e.detail.hook.trigger.value.toLowerCase();
|
||||
var config = e.detail.hook.config.droplabFilter;
|
||||
var matches = [];
|
||||
var filterFunction;
|
||||
// will only work on dynamically set data
|
||||
if(!data){
|
||||
return;
|
||||
}
|
||||
|
||||
if (config && config.filterFunction && typeof config.filterFunction === 'function') {
|
||||
filterFunction = config.filterFunction;
|
||||
} else {
|
||||
filterFunction = function(o){
|
||||
// cheap string search
|
||||
o.droplab_hidden = o[config.template].toLowerCase().indexOf(value) === -1;
|
||||
return o;
|
||||
};
|
||||
}
|
||||
|
||||
dataHiddenCount = data.filter(function(o) {
|
||||
return !o.droplab_hidden;
|
||||
}).length;
|
||||
|
||||
matches = data.map(function(o) {
|
||||
return filterFunction(o, value);
|
||||
});
|
||||
|
||||
hiddenCount = matches.filter(function(o) {
|
||||
return !o.droplab_hidden;
|
||||
}).length;
|
||||
|
||||
if (dataHiddenCount !== hiddenCount) {
|
||||
list.render(matches);
|
||||
list.currentIndex = 0;
|
||||
}
|
||||
},
|
||||
|
||||
init: function init(hookInput) {
|
||||
var config = hookInput.config.droplabFilter;
|
||||
|
||||
if (!config || (!config.template && !config.filterFunction)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.hookInput = hookInput;
|
||||
this.hookInput.trigger.addEventListener('keyup.dl', this.keydownWrapper);
|
||||
this.hookInput.trigger.addEventListener('mousedown.dl', this.keydownWrapper);
|
||||
},
|
||||
|
||||
destroy: function destroy(){
|
||||
this.hookInput.trigger.removeEventListener('keyup.dl', this.keydownWrapper);
|
||||
this.hookInput.trigger.removeEventListener('mousedown.dl', this.keydownWrapper);
|
||||
}
|
||||
};
|
||||
});
|
||||
},{"../window":2}],2:[function(require,module,exports){
|
||||
module.exports = function(callback) {
|
||||
return (function() {
|
||||
callback(this);
|
||||
}).call(null);
|
||||
};
|
||||
|
||||
},{}]},{},[1])(1)
|
||||
});
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import DropDown from './drop_down';
|
||||
|
||||
var Hook = function(trigger, list, plugins, config){
|
||||
this.trigger = trigger;
|
||||
this.list = new DropDown(list);
|
||||
this.type = 'Hook';
|
||||
this.event = 'click';
|
||||
this.plugins = plugins || [];
|
||||
this.config = config || {};
|
||||
this.id = trigger.id;
|
||||
};
|
||||
|
||||
Object.assign(Hook.prototype, {
|
||||
|
||||
addEvents: function(){},
|
||||
|
||||
constructor: Hook,
|
||||
});
|
||||
|
||||
export default Hook;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import Hook from './hook';
|
||||
|
||||
var HookButton = function(trigger, list, plugins, config) {
|
||||
Hook.call(this, trigger, list, plugins, config);
|
||||
|
||||
this.type = 'button';
|
||||
this.event = 'click';
|
||||
|
||||
this.eventWrapper = {};
|
||||
|
||||
this.addEvents();
|
||||
this.addPlugins();
|
||||
};
|
||||
|
||||
HookButton.prototype = Object.create(Hook.prototype);
|
||||
|
||||
Object.assign(HookButton.prototype, {
|
||||
addPlugins: function() {
|
||||
this.plugins.forEach(plugin => plugin.init(this));
|
||||
},
|
||||
|
||||
clicked: function(e){
|
||||
var buttonEvent = new CustomEvent('click.dl', {
|
||||
detail: {
|
||||
hook: this,
|
||||
},
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
e.target.dispatchEvent(buttonEvent);
|
||||
|
||||
this.list.toggle();
|
||||
},
|
||||
|
||||
addEvents: function(){
|
||||
this.eventWrapper.clicked = this.clicked.bind(this);
|
||||
this.trigger.addEventListener('click', this.eventWrapper.clicked);
|
||||
},
|
||||
|
||||
removeEvents: function(){
|
||||
this.trigger.removeEventListener('click', this.eventWrapper.clicked);
|
||||
},
|
||||
|
||||
restoreInitialState: function() {
|
||||
this.list.list.innerHTML = this.list.initialState;
|
||||
},
|
||||
|
||||
removePlugins: function() {
|
||||
this.plugins.forEach(plugin => plugin.destroy());
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.restoreInitialState();
|
||||
|
||||
this.removeEvents();
|
||||
this.removePlugins();
|
||||
},
|
||||
|
||||
constructor: HookButton,
|
||||
});
|
||||
|
||||
|
||||
export default HookButton;
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import Hook from './hook';
|
||||
|
||||
var HookInput = function(trigger, list, plugins, config) {
|
||||
Hook.call(this, trigger, list, plugins, config);
|
||||
|
||||
this.type = 'input';
|
||||
this.event = 'input';
|
||||
|
||||
this.eventWrapper = {};
|
||||
|
||||
this.addEvents();
|
||||
this.addPlugins();
|
||||
};
|
||||
|
||||
Object.assign(HookInput.prototype, {
|
||||
addPlugins: function() {
|
||||
this.plugins.forEach(plugin => plugin.init(this));
|
||||
},
|
||||
|
||||
addEvents: function(){
|
||||
this.eventWrapper.mousedown = this.mousedown.bind(this);
|
||||
this.eventWrapper.input = this.input.bind(this);
|
||||
this.eventWrapper.keyup = this.keyup.bind(this);
|
||||
this.eventWrapper.keydown = this.keydown.bind(this);
|
||||
|
||||
this.trigger.addEventListener('mousedown', this.eventWrapper.mousedown);
|
||||
this.trigger.addEventListener('input', this.eventWrapper.input);
|
||||
this.trigger.addEventListener('keyup', this.eventWrapper.keyup);
|
||||
this.trigger.addEventListener('keydown', this.eventWrapper.keydown);
|
||||
},
|
||||
|
||||
removeEvents: function() {
|
||||
this.hasRemovedEvents = true;
|
||||
|
||||
this.trigger.removeEventListener('mousedown', this.eventWrapper.mousedown);
|
||||
this.trigger.removeEventListener('input', this.eventWrapper.input);
|
||||
this.trigger.removeEventListener('keyup', this.eventWrapper.keyup);
|
||||
this.trigger.removeEventListener('keydown', this.eventWrapper.keydown);
|
||||
},
|
||||
|
||||
input: function(e) {
|
||||
if(this.hasRemovedEvents) return;
|
||||
|
||||
this.list.show();
|
||||
|
||||
const inputEvent = new CustomEvent('input.dl', {
|
||||
detail: {
|
||||
hook: this,
|
||||
text: e.target.value,
|
||||
},
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
e.target.dispatchEvent(inputEvent);
|
||||
},
|
||||
|
||||
mousedown: function(e) {
|
||||
if (this.hasRemovedEvents) return;
|
||||
|
||||
const mouseEvent = new CustomEvent('mousedown.dl', {
|
||||
detail: {
|
||||
hook: this,
|
||||
text: e.target.value,
|
||||
},
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
});
|
||||
e.target.dispatchEvent(mouseEvent);
|
||||
},
|
||||
|
||||
keyup: function(e) {
|
||||
if (this.hasRemovedEvents) return;
|
||||
|
||||
this.keyEvent(e, 'keyup.dl');
|
||||
},
|
||||
|
||||
keydown: function(e) {
|
||||
if (this.hasRemovedEvents) return;
|
||||
|
||||
this.keyEvent(e, 'keydown.dl');
|
||||
},
|
||||
|
||||
keyEvent: function(e, eventName) {
|
||||
this.list.show();
|
||||
|
||||
const keyEvent = new CustomEvent(eventName, {
|
||||
detail: {
|
||||
hook: this,
|
||||
text: e.target.value,
|
||||
which: e.which,
|
||||
key: e.key,
|
||||
},
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
});
|
||||
e.target.dispatchEvent(keyEvent);
|
||||
},
|
||||
|
||||
restoreInitialState: function() {
|
||||
this.list.list.innerHTML = this.list.initialState;
|
||||
},
|
||||
|
||||
removePlugins: function() {
|
||||
this.plugins.forEach(plugin => plugin.destroy());
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.restoreInitialState();
|
||||
|
||||
this.removeEvents();
|
||||
this.removePlugins();
|
||||
|
||||
this.list.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
export default HookInput;
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import { ACTIVE_CLASS } from './constants';
|
||||
|
||||
const Keyboard = function () {
|
||||
var currentKey;
|
||||
var currentFocus;
|
||||
var isUpArrow = false;
|
||||
var isDownArrow = false;
|
||||
var removeHighlight = function removeHighlight(list) {
|
||||
var itemElements = Array.prototype.slice.call(list.list.querySelectorAll('li:not(.divider)'), 0);
|
||||
var listItems = [];
|
||||
for(var i = 0; i < itemElements.length; i++) {
|
||||
var listItem = itemElements[i];
|
||||
listItem.classList.remove(ACTIVE_CLASS);
|
||||
|
||||
if (listItem.style.display !== 'none') {
|
||||
listItems.push(listItem);
|
||||
}
|
||||
}
|
||||
return listItems;
|
||||
};
|
||||
|
||||
var setMenuForArrows = function setMenuForArrows(list) {
|
||||
var listItems = removeHighlight(list);
|
||||
if(list.currentIndex>0){
|
||||
if(!listItems[list.currentIndex-1]){
|
||||
list.currentIndex = list.currentIndex-1;
|
||||
}
|
||||
|
||||
if (listItems[list.currentIndex-1]) {
|
||||
var el = listItems[list.currentIndex-1];
|
||||
var filterDropdownEl = el.closest('.filter-dropdown');
|
||||
el.classList.add(ACTIVE_CLASS);
|
||||
|
||||
if (filterDropdownEl) {
|
||||
var filterDropdownBottom = filterDropdownEl.offsetHeight;
|
||||
var elOffsetTop = el.offsetTop - 30;
|
||||
|
||||
if (elOffsetTop > filterDropdownBottom) {
|
||||
filterDropdownEl.scrollTop = elOffsetTop - filterDropdownBottom;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var mousedown = function mousedown(e) {
|
||||
var list = e.detail.hook.list;
|
||||
removeHighlight(list);
|
||||
list.show();
|
||||
list.currentIndex = 0;
|
||||
isUpArrow = false;
|
||||
isDownArrow = false;
|
||||
};
|
||||
var selectItem = function selectItem(list) {
|
||||
var listItems = removeHighlight(list);
|
||||
var currentItem = listItems[list.currentIndex-1];
|
||||
var listEvent = new CustomEvent('click.dl', {
|
||||
detail: {
|
||||
list: list,
|
||||
selected: currentItem,
|
||||
data: currentItem.dataset,
|
||||
},
|
||||
});
|
||||
list.list.dispatchEvent(listEvent);
|
||||
list.hide();
|
||||
}
|
||||
|
||||
var keydown = function keydown(e){
|
||||
var typedOn = e.target;
|
||||
var list = e.detail.hook.list;
|
||||
var currentIndex = list.currentIndex;
|
||||
isUpArrow = false;
|
||||
isDownArrow = false;
|
||||
|
||||
if(e.detail.which){
|
||||
currentKey = e.detail.which;
|
||||
if(currentKey === 13){
|
||||
selectItem(e.detail.hook.list);
|
||||
return;
|
||||
}
|
||||
if(currentKey === 38) {
|
||||
isUpArrow = true;
|
||||
}
|
||||
if(currentKey === 40) {
|
||||
isDownArrow = true;
|
||||
}
|
||||
} else if(e.detail.key) {
|
||||
currentKey = e.detail.key;
|
||||
if(currentKey === 'Enter'){
|
||||
selectItem(e.detail.hook.list);
|
||||
return;
|
||||
}
|
||||
if(currentKey === 'ArrowUp') {
|
||||
isUpArrow = true;
|
||||
}
|
||||
if(currentKey === 'ArrowDown') {
|
||||
isDownArrow = true;
|
||||
}
|
||||
}
|
||||
if(isUpArrow){ currentIndex--; }
|
||||
if(isDownArrow){ currentIndex++; }
|
||||
if(currentIndex < 0){ currentIndex = 0; }
|
||||
list.currentIndex = currentIndex;
|
||||
setMenuForArrows(e.detail.hook.list);
|
||||
};
|
||||
|
||||
document.addEventListener('mousedown.dl', mousedown);
|
||||
document.addEventListener('keydown.dl', keydown);
|
||||
};
|
||||
|
||||
export default Keyboard;
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
/* eslint-disable */
|
||||
|
||||
const Ajax = {
|
||||
_loadUrlData: function _loadUrlData(url) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open('GET', url, true);
|
||||
xhr.onreadystatechange = function () {
|
||||
if(xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
self.cache[url] = data;
|
||||
return resolve(data);
|
||||
} else {
|
||||
return reject([xhr.responseText, xhr.status]);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
},
|
||||
_loadData: function _loadData(data, config, self) {
|
||||
if (config.loadingTemplate) {
|
||||
var dataLoadingTemplate = self.hook.list.list.querySelector('[data-loading-template]');
|
||||
if (dataLoadingTemplate) dataLoadingTemplate.outerHTML = self.listTemplate;
|
||||
}
|
||||
|
||||
if (!self.destroyed) self.hook.list[config.method].call(self.hook.list, data);
|
||||
},
|
||||
init: function init(hook) {
|
||||
var self = this;
|
||||
self.destroyed = false;
|
||||
self.cache = self.cache || {};
|
||||
var config = hook.config.Ajax;
|
||||
this.hook = hook;
|
||||
if (!config || !config.endpoint || !config.method) {
|
||||
return;
|
||||
}
|
||||
if (config.method !== 'setData' && config.method !== 'addData') {
|
||||
return;
|
||||
}
|
||||
if (config.loadingTemplate) {
|
||||
var dynamicList = hook.list.list.querySelector('[data-dynamic]');
|
||||
var loadingTemplate = document.createElement('div');
|
||||
loadingTemplate.innerHTML = config.loadingTemplate;
|
||||
loadingTemplate.setAttribute('data-loading-template', '');
|
||||
this.listTemplate = dynamicList.outerHTML;
|
||||
dynamicList.outerHTML = loadingTemplate.outerHTML;
|
||||
}
|
||||
if (self.cache[config.endpoint]) {
|
||||
self._loadData(self.cache[config.endpoint], config, self);
|
||||
} else {
|
||||
this._loadUrlData(config.endpoint)
|
||||
.then(function(d) {
|
||||
self._loadData(d, config, self);
|
||||
}, config.onError).catch(config.onError);
|
||||
}
|
||||
},
|
||||
destroy: function() {
|
||||
this.destroyed = true;
|
||||
}
|
||||
};
|
||||
|
||||
export default Ajax;
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
/* eslint-disable */
|
||||
|
||||
const AjaxFilter = {
|
||||
init: function(hook) {
|
||||
this.destroyed = false;
|
||||
this.hook = hook;
|
||||
this.notLoading();
|
||||
|
||||
this.eventWrapper = {};
|
||||
this.eventWrapper.debounceTrigger = this.debounceTrigger.bind(this);
|
||||
this.hook.trigger.addEventListener('keydown.dl', this.eventWrapper.debounceTrigger);
|
||||
this.hook.trigger.addEventListener('focus', this.eventWrapper.debounceTrigger);
|
||||
|
||||
this.trigger(true);
|
||||
},
|
||||
|
||||
notLoading: function notLoading() {
|
||||
this.loading = false;
|
||||
},
|
||||
|
||||
debounceTrigger: function debounceTrigger(e) {
|
||||
var NON_CHARACTER_KEYS = [16, 17, 18, 20, 37, 38, 39, 40, 91, 93];
|
||||
var invalidKeyPressed = NON_CHARACTER_KEYS.indexOf(e.detail.which || e.detail.keyCode) > -1;
|
||||
var focusEvent = e.type === 'focus';
|
||||
if (invalidKeyPressed || this.loading) {
|
||||
return;
|
||||
}
|
||||
if (this.timeout) {
|
||||
clearTimeout(this.timeout);
|
||||
}
|
||||
this.timeout = setTimeout(this.trigger.bind(this, focusEvent), 200);
|
||||
},
|
||||
|
||||
trigger: function trigger(getEntireList) {
|
||||
var config = this.hook.config.AjaxFilter;
|
||||
var searchValue = this.trigger.value;
|
||||
if (!config || !config.endpoint || !config.searchKey) {
|
||||
return;
|
||||
}
|
||||
if (config.searchValueFunction) {
|
||||
searchValue = config.searchValueFunction();
|
||||
}
|
||||
if (config.loadingTemplate && this.hook.list.data === undefined ||
|
||||
this.hook.list.data.length === 0) {
|
||||
var dynamicList = this.hook.list.list.querySelector('[data-dynamic]');
|
||||
var loadingTemplate = document.createElement('div');
|
||||
loadingTemplate.innerHTML = config.loadingTemplate;
|
||||
loadingTemplate.setAttribute('data-loading-template', true);
|
||||
this.listTemplate = dynamicList.outerHTML;
|
||||
dynamicList.outerHTML = loadingTemplate.outerHTML;
|
||||
}
|
||||
if (getEntireList) {
|
||||
searchValue = '';
|
||||
}
|
||||
if (config.searchKey === searchValue) {
|
||||
return this.list.show();
|
||||
}
|
||||
this.loading = true;
|
||||
var params = config.params || {};
|
||||
params[config.searchKey] = searchValue;
|
||||
var self = this;
|
||||
self.cache = self.cache || {};
|
||||
var url = config.endpoint + this.buildParams(params);
|
||||
var urlCachedData = self.cache[url];
|
||||
if (urlCachedData) {
|
||||
self._loadData(urlCachedData, config, self);
|
||||
} else {
|
||||
this._loadUrlData(url)
|
||||
.then(function(data) {
|
||||
self._loadData(data, config, self);
|
||||
}, config.onError).catch(config.onError);
|
||||
}
|
||||
},
|
||||
|
||||
_loadUrlData: function _loadUrlData(url) {
|
||||
var self = this;
|
||||
return new Promise(function(resolve, reject) {
|
||||
var xhr = new XMLHttpRequest;
|
||||
xhr.open('GET', url, true);
|
||||
xhr.onreadystatechange = function () {
|
||||
if(xhr.readyState === XMLHttpRequest.DONE) {
|
||||
if (xhr.status === 200) {
|
||||
var data = JSON.parse(xhr.responseText);
|
||||
self.cache[url] = data;
|
||||
return resolve(data);
|
||||
} else {
|
||||
return reject([xhr.responseText, xhr.status]);
|
||||
}
|
||||
}
|
||||
};
|
||||
xhr.send();
|
||||
});
|
||||
},
|
||||
|
||||
_loadData: function _loadData(data, config, self) {
|
||||
const list = self.hook.list;
|
||||
if (config.loadingTemplate && list.data === undefined ||
|
||||
list.data.length === 0) {
|
||||
const dataLoadingTemplate = list.list.querySelector('[data-loading-template]');
|
||||
if (dataLoadingTemplate) {
|
||||
dataLoadingTemplate.outerHTML = self.listTemplate;
|
||||
}
|
||||
}
|
||||
if (!self.destroyed) {
|
||||
var hookListChildren = list.list.children;
|
||||
var onlyDynamicList = hookListChildren.length === 1 && hookListChildren[0].hasAttribute('data-dynamic');
|
||||
if (onlyDynamicList && data.length === 0) {
|
||||
list.hide();
|
||||
}
|
||||
list.setData.call(list, data);
|
||||
}
|
||||
self.notLoading();
|
||||
list.currentIndex = 0;
|
||||
},
|
||||
|
||||
buildParams: function(params) {
|
||||
if (!params) return '';
|
||||
var paramsArray = Object.keys(params).map(function(param) {
|
||||
return param + '=' + (params[param] || '');
|
||||
});
|
||||
return '?' + paramsArray.join('&');
|
||||
},
|
||||
|
||||
destroy: function destroy() {
|
||||
if (this.timeout)clearTimeout(this.timeout);
|
||||
this.destroyed = true;
|
||||
|
||||
this.hook.trigger.removeEventListener('keydown.dl', this.eventWrapper.debounceTrigger);
|
||||
this.hook.trigger.removeEventListener('focus', this.eventWrapper.debounceTrigger);
|
||||
}
|
||||
};
|
||||
|
||||
export default AjaxFilter;
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
/* eslint-disable */
|
||||
|
||||
const Filter = {
|
||||
keydown: function(e){
|
||||
if (this.destroyed) return;
|
||||
|
||||
var hiddenCount = 0;
|
||||
var dataHiddenCount = 0;
|
||||
|
||||
var list = e.detail.hook.list;
|
||||
var data = list.data;
|
||||
var value = e.detail.hook.trigger.value.toLowerCase();
|
||||
var config = e.detail.hook.config.Filter;
|
||||
var matches = [];
|
||||
var filterFunction;
|
||||
// will only work on dynamically set data
|
||||
if(!data){
|
||||
return;
|
||||
}
|
||||
|
||||
if (config && config.filterFunction && typeof config.filterFunction === 'function') {
|
||||
filterFunction = config.filterFunction;
|
||||
} else {
|
||||
filterFunction = function(o){
|
||||
// cheap string search
|
||||
o.droplab_hidden = o[config.template].toLowerCase().indexOf(value) === -1;
|
||||
return o;
|
||||
};
|
||||
}
|
||||
|
||||
dataHiddenCount = data.filter(function(o) {
|
||||
return !o.droplab_hidden;
|
||||
}).length;
|
||||
|
||||
matches = data.map(function(o) {
|
||||
return filterFunction(o, value);
|
||||
});
|
||||
|
||||
hiddenCount = matches.filter(function(o) {
|
||||
return !o.droplab_hidden;
|
||||
}).length;
|
||||
|
||||
if (dataHiddenCount !== hiddenCount) {
|
||||
list.setData(matches);
|
||||
list.currentIndex = 0;
|
||||
}
|
||||
},
|
||||
|
||||
debounceKeydown: function debounceKeydown(e) {
|
||||
if ([
|
||||
13, // enter
|
||||
16, // shift
|
||||
17, // ctrl
|
||||
18, // alt
|
||||
20, // caps lock
|
||||
37, // left arrow
|
||||
38, // up arrow
|
||||
39, // right arrow
|
||||
40, // down arrow
|
||||
91, // left window
|
||||
92, // right window
|
||||
93, // select
|
||||
].indexOf(e.detail.which || e.detail.keyCode) > -1) return;
|
||||
|
||||
if (this.timeout) clearTimeout(this.timeout);
|
||||
this.timeout = setTimeout(this.keydown.bind(this, e), 200);
|
||||
},
|
||||
|
||||
init: function init(hook) {
|
||||
var config = hook.config.Filter;
|
||||
|
||||
if (!config || !config.template) return;
|
||||
|
||||
this.hook = hook;
|
||||
this.destroyed = false;
|
||||
|
||||
this.eventWrapper = {};
|
||||
this.eventWrapper.debounceKeydown = this.debounceKeydown.bind(this);
|
||||
|
||||
this.hook.trigger.addEventListener('keydown.dl', this.eventWrapper.debounceKeydown);
|
||||
this.hook.trigger.addEventListener('mousedown.dl', this.eventWrapper.debounceKeydown);
|
||||
|
||||
this.debounceKeydown({ detail: { hook: this.hook } });
|
||||
},
|
||||
|
||||
destroy: function destroy() {
|
||||
if (this.timeout) clearTimeout(this.timeout);
|
||||
this.destroyed = true;
|
||||
|
||||
this.hook.trigger.removeEventListener('keydown.dl', this.eventWrapper.debounceKeydown);
|
||||
this.hook.trigger.removeEventListener('mousedown.dl', this.eventWrapper.debounceKeydown);
|
||||
}
|
||||
};
|
||||
|
||||
export default Filter;
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/* eslint-disable */
|
||||
|
||||
const InputSetter = {
|
||||
init(hook) {
|
||||
this.hook = hook;
|
||||
this.destroyed = false;
|
||||
this.config = hook.config.InputSetter || (this.hook.config.InputSetter = {});
|
||||
|
||||
this.eventWrapper = {};
|
||||
|
||||
this.addEvents();
|
||||
},
|
||||
|
||||
addEvents() {
|
||||
this.eventWrapper.setInputs = this.setInputs.bind(this);
|
||||
this.hook.list.list.addEventListener('click.dl', this.eventWrapper.setInputs);
|
||||
},
|
||||
|
||||
removeEvents() {
|
||||
this.hook.list.list.removeEventListener('click.dl', this.eventWrapper.setInputs);
|
||||
},
|
||||
|
||||
setInputs(e) {
|
||||
if (this.destroyed) return;
|
||||
|
||||
const selectedItem = e.detail.selected;
|
||||
|
||||
if (!Array.isArray(this.config)) this.config = [this.config];
|
||||
|
||||
this.config.forEach(config => this.setInput(config, selectedItem));
|
||||
},
|
||||
|
||||
setInput(config, selectedItem) {
|
||||
const input = config.input || this.hook.trigger;
|
||||
const newValue = selectedItem.getAttribute(config.valueAttribute);
|
||||
const inputAttribute = config.inputAttribute;
|
||||
|
||||
if (!newValue) return;
|
||||
|
||||
if (input.hasAttribute(inputAttribute)) return input.setAttribute(inputAttribute, newValue);
|
||||
if (input.tagName === 'INPUT') return input.value = newValue;
|
||||
return input.textContent = newValue;
|
||||
},
|
||||
|
||||
destroy() {
|
||||
this.destroyed = true;
|
||||
|
||||
this.removeEvents();
|
||||
},
|
||||
};
|
||||
|
||||
export default InputSetter;
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import { DATA_TRIGGER, DATA_DROPDOWN } from './constants';
|
||||
|
||||
const utils = {
|
||||
toCamelCase(attr) {
|
||||
return this.camelize(attr.split('-').slice(1).join(' '));
|
||||
},
|
||||
|
||||
t(s, d) {
|
||||
for (const p in d) {
|
||||
if (Object.prototype.hasOwnProperty.call(d, p)) {
|
||||
s = s.replace(new RegExp(`{{${p}}}`, 'g'), d[p]);
|
||||
}
|
||||
}
|
||||
return s;
|
||||
},
|
||||
|
||||
camelize(str) {
|
||||
return str.replace(/(?:^\w|[A-Z]|\b\w)/g, (letter, index) => {
|
||||
return index === 0 ? letter.toLowerCase() : letter.toUpperCase();
|
||||
}).replace(/\s+/g, '');
|
||||
},
|
||||
|
||||
closest(thisTag, stopTag) {
|
||||
while (thisTag && thisTag.tagName !== stopTag && thisTag.tagName !== 'HTML') {
|
||||
thisTag = thisTag.parentNode;
|
||||
}
|
||||
return thisTag;
|
||||
},
|
||||
|
||||
isDropDownParts(target) {
|
||||
if (!target || target.tagName === 'HTML') return false;
|
||||
return target.hasAttribute(DATA_TRIGGER) || target.hasAttribute(DATA_DROPDOWN);
|
||||
},
|
||||
};
|
||||
|
||||
export default utils;
|
||||
|
|
@ -1,13 +1,13 @@
|
|||
require('./filtered_search_dropdown');
|
||||
import Filter from '~/droplab/plugins/filter';
|
||||
|
||||
/* global droplabFilter */
|
||||
require('./filtered_search_dropdown');
|
||||
|
||||
(() => {
|
||||
class DropdownHint extends gl.FilteredSearchDropdown {
|
||||
constructor(droplab, dropdown, input, filter) {
|
||||
super(droplab, dropdown, input, filter);
|
||||
this.config = {
|
||||
droplabFilter: {
|
||||
Filter: {
|
||||
template: 'hint',
|
||||
filterFunction: gl.DropdownUtils.filterHint.bind(null, input),
|
||||
},
|
||||
|
|
@ -69,12 +69,12 @@ require('./filtered_search_dropdown');
|
|||
}
|
||||
});
|
||||
|
||||
this.droplab.changeHookList(this.hookId, this.dropdown, [droplabFilter], this.config);
|
||||
this.droplab.changeHookList(this.hookId, this.dropdown, [Filter], this.config);
|
||||
this.droplab.setData(this.hookId, dropdownData);
|
||||
}
|
||||
|
||||
init() {
|
||||
this.droplab.addHook(this.input, this.dropdown, [droplabFilter], this.config).init();
|
||||
this.droplab.addHook(this.input, this.dropdown, [Filter], this.config).init();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
require('./filtered_search_dropdown');
|
||||
/* global Flash */
|
||||
|
||||
/* global droplabAjax */
|
||||
/* global droplabFilter */
|
||||
import Ajax from '~/droplab/plugins/ajax';
|
||||
import Filter from '~/droplab/plugins/filter';
|
||||
|
||||
require('./filtered_search_dropdown');
|
||||
|
||||
(() => {
|
||||
class DropdownNonUser extends gl.FilteredSearchDropdown {
|
||||
|
|
@ -9,13 +11,19 @@ require('./filtered_search_dropdown');
|
|||
super(droplab, dropdown, input, filter);
|
||||
this.symbol = symbol;
|
||||
this.config = {
|
||||
droplabAjax: {
|
||||
Ajax: {
|
||||
endpoint,
|
||||
method: 'setData',
|
||||
loadingTemplate: this.loadingTemplate,
|
||||
onError() {
|
||||
/* eslint-disable no-new */
|
||||
new Flash('An error occured fetching the dropdown data.');
|
||||
/* eslint-enable no-new */
|
||||
},
|
||||
},
|
||||
droplabFilter: {
|
||||
Filter: {
|
||||
filterFunction: gl.DropdownUtils.filterWithSymbol.bind(null, this.symbol, input),
|
||||
template: 'title',
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -29,13 +37,13 @@ require('./filtered_search_dropdown');
|
|||
|
||||
renderContent(forceShowList = false) {
|
||||
this.droplab
|
||||
.changeHookList(this.hookId, this.dropdown, [droplabAjax, droplabFilter], this.config);
|
||||
.changeHookList(this.hookId, this.dropdown, [Ajax, Filter], this.config);
|
||||
super.renderContent(forceShowList);
|
||||
}
|
||||
|
||||
init() {
|
||||
this.droplab
|
||||
.addHook(this.input, this.dropdown, [droplabAjax, droplabFilter], this.config).init();
|
||||
.addHook(this.input, this.dropdown, [Ajax, Filter], this.config).init();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,13 +1,15 @@
|
|||
require('./filtered_search_dropdown');
|
||||
/* global Flash */
|
||||
|
||||
/* global droplabAjaxFilter */
|
||||
import AjaxFilter from '~/droplab/plugins/ajax_filter';
|
||||
|
||||
require('./filtered_search_dropdown');
|
||||
|
||||
(() => {
|
||||
class DropdownUser extends gl.FilteredSearchDropdown {
|
||||
constructor(droplab, dropdown, input, filter) {
|
||||
super(droplab, dropdown, input, filter);
|
||||
this.config = {
|
||||
droplabAjaxFilter: {
|
||||
AjaxFilter: {
|
||||
endpoint: `${gon.relative_url_root || ''}/autocomplete/users.json`,
|
||||
searchKey: 'search',
|
||||
params: {
|
||||
|
|
@ -18,6 +20,11 @@ require('./filtered_search_dropdown');
|
|||
},
|
||||
searchValueFunction: this.getSearchInput.bind(this),
|
||||
loadingTemplate: this.loadingTemplate,
|
||||
onError() {
|
||||
/* eslint-disable no-new */
|
||||
new Flash('An error occured fetching the dropdown data.');
|
||||
/* eslint-enable no-new */
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
|
|
@ -28,7 +35,7 @@ require('./filtered_search_dropdown');
|
|||
}
|
||||
|
||||
renderContent(forceShowList = false) {
|
||||
this.droplab.changeHookList(this.hookId, this.dropdown, [droplabAjaxFilter], this.config);
|
||||
this.droplab.changeHookList(this.hookId, this.dropdown, [AjaxFilter], this.config);
|
||||
super.renderContent(forceShowList);
|
||||
}
|
||||
|
||||
|
|
@ -56,7 +63,7 @@ require('./filtered_search_dropdown');
|
|||
}
|
||||
|
||||
init() {
|
||||
this.droplab.addHook(this.input, this.dropdown, [droplabAjaxFilter], this.config).init();
|
||||
this.droplab.addHook(this.input, this.dropdown, [AjaxFilter], this.config).init();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
class FilteredSearchDropdown {
|
||||
constructor(droplab, dropdown, input, filter) {
|
||||
this.droplab = droplab;
|
||||
this.hookId = input && input.getAttribute('data-id');
|
||||
this.hookId = input && input.id;
|
||||
this.input = input;
|
||||
this.filter = filter;
|
||||
this.dropdown = dropdown;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* global DropLab */
|
||||
import DropLab from '~/droplab/drop_lab';
|
||||
import FilteredSearchContainer from './container';
|
||||
|
||||
(() => {
|
||||
|
|
|
|||
|
|
@ -154,7 +154,7 @@ import eventHub from './event_hub';
|
|||
if (e.keyCode === 13) {
|
||||
const dropdown = this.dropdownManager.mapping[this.dropdownManager.currentDropdown];
|
||||
const dropdownEl = dropdown.element;
|
||||
const activeElements = dropdownEl.querySelectorAll('.dropdown-active');
|
||||
const activeElements = dropdownEl.querySelectorAll('.droplab-item-active');
|
||||
|
||||
e.preventDefault();
|
||||
|
||||
|
|
|
|||
|
|
@ -75,12 +75,6 @@ import './u2f/error';
|
|||
import './u2f/register';
|
||||
import './u2f/util';
|
||||
|
||||
// droplab
|
||||
import './droplab/droplab';
|
||||
import './droplab/droplab_ajax';
|
||||
import './droplab/droplab_ajax_filter';
|
||||
import './droplab/droplab_filter';
|
||||
|
||||
// everything else
|
||||
import './abuse_reports';
|
||||
import './activities';
|
||||
|
|
|
|||
|
|
@ -446,10 +446,8 @@
|
|||
}
|
||||
}
|
||||
|
||||
.filter-dropdown-item.dropdown-active {
|
||||
.btn {
|
||||
@extend %filter-dropdown-item-btn-hover;
|
||||
}
|
||||
.filter-dropdown-item.droplab-item-active .btn {
|
||||
@extend %filter-dropdown-item-btn-hover;
|
||||
}
|
||||
|
||||
.filter-dropdown-loading {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@
|
|||
.scroll-container
|
||||
%ul.tokens-container.list-unstyled
|
||||
%li.input-token
|
||||
%input.form-control.filtered-search{ placeholder: 'Search or filter results...', data: { id: "filtered-search-#{type.to_s}", 'project-id' => @project.id, 'username-params' => @users.to_json(only: [:id, :username]), 'base-endpoint' => namespace_project_path(@project.namespace, @project) } }
|
||||
%input.form-control.filtered-search{ id: "filtered-search-#{type.to_s}", placeholder: 'Search or filter results...', data: { 'project-id' => @project.id, 'username-params' => @users.to_json(only: [:id, :username]), 'base-endpoint' => namespace_project_path(@project.namespace, @project) } }
|
||||
= icon('filter')
|
||||
%button.clear-search.hidden{ type: 'button' }
|
||||
= icon('times')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe 'Dropdown hint', js: true, feature: true do
|
||||
describe 'Dropdown hint', :js, :feature do
|
||||
include FilteredSearchHelpers
|
||||
include WaitForAjax
|
||||
|
||||
|
|
@ -9,10 +9,6 @@ describe 'Dropdown hint', js: true, feature: true do
|
|||
let(:filtered_search) { find('.filtered-search') }
|
||||
let(:js_dropdown_hint) { '#js-dropdown-hint' }
|
||||
|
||||
def dropdown_hint_size
|
||||
page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size
|
||||
end
|
||||
|
||||
def click_hint(text)
|
||||
find('#js-dropdown-hint .filter-dropdown .filter-dropdown-item', text: text).click
|
||||
end
|
||||
|
|
@ -46,14 +42,16 @@ describe 'Dropdown hint', js: true, feature: true do
|
|||
it 'does not filter `Press Enter or click to search`' do
|
||||
filtered_search.set('randomtext')
|
||||
|
||||
expect(page).to have_css(js_dropdown_hint, text: 'Press Enter or click to search', visible: false)
|
||||
expect(dropdown_hint_size).to eq(0)
|
||||
hint_dropdown = find(js_dropdown_hint)
|
||||
|
||||
expect(hint_dropdown).to have_content('Press Enter or click to search')
|
||||
expect(hint_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 0)
|
||||
end
|
||||
|
||||
it 'filters with text' do
|
||||
filtered_search.set('a')
|
||||
|
||||
expect(dropdown_hint_size).to eq(3)
|
||||
expect(find(js_dropdown_hint)).to have_selector('.filter-dropdown .filter-dropdown-item', count: 3)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -28,10 +28,6 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
filter_dropdown.find('.filter-dropdown-item', text: text).click
|
||||
end
|
||||
|
||||
def dropdown_label_size
|
||||
filter_dropdown.all('.filter-dropdown-item').size
|
||||
end
|
||||
|
||||
def clear_search_field
|
||||
find('.filtered-search-box .clear-search').click
|
||||
end
|
||||
|
|
@ -81,7 +77,7 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
filtered_search.set('label:')
|
||||
|
||||
expect(filter_dropdown).to have_content(bug_label.title)
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -97,7 +93,8 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: bug_label.title)).to be_visible
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: uppercase_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(2)
|
||||
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 2)
|
||||
|
||||
clear_search_field
|
||||
init_label_search
|
||||
|
|
@ -106,14 +103,14 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: bug_label.title)).to be_visible
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: uppercase_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(2)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 2)
|
||||
end
|
||||
|
||||
it 'filters by multiple words with or without symbol' do
|
||||
filtered_search.send_keys('Hig')
|
||||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: two_words_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
|
||||
clear_search_field
|
||||
init_label_search
|
||||
|
|
@ -121,14 +118,14 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
filtered_search.send_keys('~Hig')
|
||||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: two_words_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
end
|
||||
|
||||
it 'filters by multiple words containing single quotes with or without symbol' do
|
||||
filtered_search.send_keys('won\'t')
|
||||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_single_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
|
||||
clear_search_field
|
||||
init_label_search
|
||||
|
|
@ -136,14 +133,14 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
filtered_search.send_keys('~won\'t')
|
||||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_single_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
end
|
||||
|
||||
it 'filters by multiple words containing double quotes with or without symbol' do
|
||||
filtered_search.send_keys('won"t')
|
||||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
|
||||
clear_search_field
|
||||
init_label_search
|
||||
|
|
@ -151,14 +148,14 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
filtered_search.send_keys('~won"t')
|
||||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: wont_fix_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
end
|
||||
|
||||
it 'filters by special characters with or without symbol' do
|
||||
filtered_search.send_keys('^+')
|
||||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: special_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
|
||||
clear_search_field
|
||||
init_label_search
|
||||
|
|
@ -166,7 +163,7 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
filtered_search.send_keys('~^+')
|
||||
|
||||
expect(filter_dropdown.find('.filter-dropdown-item', text: special_label.title)).to be_visible
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -280,13 +277,13 @@ describe 'Dropdown label', js: true, feature: true do
|
|||
create(:label, project: project, title: 'bug-label')
|
||||
init_label_search
|
||||
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
|
||||
create(:label, project: project)
|
||||
clear_search_field
|
||||
init_label_search
|
||||
|
||||
expect(dropdown_label_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown-item', count: 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -65,7 +65,7 @@ describe 'Dropdown milestone', :feature, :js do
|
|||
it 'should load all the milestones when opened' do
|
||||
filtered_search.set('milestone:')
|
||||
|
||||
expect(dropdown_milestone_size).to be > 0
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 6)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -84,37 +84,37 @@ describe 'Dropdown milestone', :feature, :js do
|
|||
it 'filters by name' do
|
||||
filtered_search.send_keys('v1')
|
||||
|
||||
expect(dropdown_milestone_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
|
||||
end
|
||||
|
||||
it 'filters by case insensitive name' do
|
||||
filtered_search.send_keys('V1')
|
||||
|
||||
expect(dropdown_milestone_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
|
||||
end
|
||||
|
||||
it 'filters by name with symbol' do
|
||||
filtered_search.send_keys('%v1')
|
||||
|
||||
expect(dropdown_milestone_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
|
||||
end
|
||||
|
||||
it 'filters by case insensitive name with symbol' do
|
||||
filtered_search.send_keys('%V1')
|
||||
|
||||
expect(dropdown_milestone_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
|
||||
end
|
||||
|
||||
it 'filters by special characters' do
|
||||
filtered_search.send_keys('(+')
|
||||
|
||||
expect(dropdown_milestone_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
|
||||
end
|
||||
|
||||
it 'filters by special characters with symbol' do
|
||||
filtered_search.send_keys('%(+')
|
||||
|
||||
expect(dropdown_milestone_size).to eq(1)
|
||||
expect(filter_dropdown).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ describe 'Search bar', js: true, feature: true do
|
|||
filtered_search.native.send_keys(:down)
|
||||
|
||||
page.within '#js-dropdown-hint' do
|
||||
expect(page).to have_selector('.dropdown-active')
|
||||
expect(page).to have_selector('.droplab-item-active')
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -79,28 +79,30 @@ describe 'Search bar', js: true, feature: true do
|
|||
|
||||
filtered_search.set('author')
|
||||
|
||||
expect(page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size).to eq(1)
|
||||
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 1)
|
||||
|
||||
find('.filtered-search-box .clear-search').click
|
||||
filtered_search.click
|
||||
|
||||
expect(page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size).to eq(original_size)
|
||||
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: original_size)
|
||||
end
|
||||
|
||||
it 'resets the dropdown filters' do
|
||||
filtered_search.click
|
||||
|
||||
hint_offset = get_left_style(find('#js-dropdown-hint')['style'])
|
||||
|
||||
filtered_search.set('a')
|
||||
hint_style = page.find('#js-dropdown-hint')['style']
|
||||
hint_offset = get_left_style(hint_style)
|
||||
|
||||
filtered_search.set('author:')
|
||||
|
||||
expect(page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size).to eq(0)
|
||||
find('#js-dropdown-hint', visible: false)
|
||||
|
||||
find('.filtered-search-box .clear-search').click
|
||||
filtered_search.click
|
||||
|
||||
expect(page.all('#js-dropdown-hint .filter-dropdown .filter-dropdown-item').size).to be > 0
|
||||
expect(get_left_style(page.find('#js-dropdown-hint')['style'])).to eq(hint_offset)
|
||||
expect(find('#js-dropdown-hint')).to have_selector('.filter-dropdown .filter-dropdown-item', count: 4)
|
||||
expect(get_left_style(find('#js-dropdown-hint')['style'])).to eq(hint_offset)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import * as constants from '~/droplab/constants';
|
||||
|
||||
describe('constants', function () {
|
||||
describe('DATA_TRIGGER', function () {
|
||||
it('should be `data-dropdown-trigger`', function() {
|
||||
expect(constants.DATA_TRIGGER).toBe('data-dropdown-trigger');
|
||||
});
|
||||
});
|
||||
|
||||
describe('DATA_DROPDOWN', function () {
|
||||
it('should be `data-dropdown`', function() {
|
||||
expect(constants.DATA_DROPDOWN).toBe('data-dropdown');
|
||||
});
|
||||
});
|
||||
|
||||
describe('SELECTED_CLASS', function () {
|
||||
it('should be `droplab-item-selected`', function() {
|
||||
expect(constants.SELECTED_CLASS).toBe('droplab-item-selected');
|
||||
});
|
||||
});
|
||||
|
||||
describe('ACTIVE_CLASS', function () {
|
||||
it('should be `droplab-item-active`', function() {
|
||||
expect(constants.ACTIVE_CLASS).toBe('droplab-item-active');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,578 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import DropDown from '~/droplab/drop_down';
|
||||
import utils from '~/droplab/utils';
|
||||
import { SELECTED_CLASS } from '~/droplab/constants';
|
||||
|
||||
describe('DropDown', function () {
|
||||
describe('class constructor', function () {
|
||||
beforeEach(function () {
|
||||
spyOn(DropDown.prototype, 'getItems');
|
||||
spyOn(DropDown.prototype, 'initTemplateString');
|
||||
spyOn(DropDown.prototype, 'addEvents');
|
||||
|
||||
this.list = { innerHTML: 'innerHTML' };
|
||||
this.dropdown = new DropDown(this.list);
|
||||
});
|
||||
|
||||
it('sets the .hidden property to true', function () {
|
||||
expect(this.dropdown.hidden).toBe(true);
|
||||
})
|
||||
|
||||
it('sets the .list property', function () {
|
||||
expect(this.dropdown.list).toBe(this.list);
|
||||
});
|
||||
|
||||
it('calls .getItems', function () {
|
||||
expect(DropDown.prototype.getItems).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls .initTemplateString', function () {
|
||||
expect(DropDown.prototype.initTemplateString).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('calls .addEvents', function () {
|
||||
expect(DropDown.prototype.addEvents).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('sets the .initialState property to the .list.innerHTML', function () {
|
||||
expect(this.dropdown.initialState).toBe(this.list.innerHTML);
|
||||
});
|
||||
|
||||
describe('if the list argument is a string', function () {
|
||||
beforeEach(function () {
|
||||
this.element = {};
|
||||
this.selector = '.selector';
|
||||
|
||||
spyOn(Document.prototype, 'querySelector').and.returnValue(this.element);
|
||||
|
||||
this.dropdown = new DropDown(this.selector);
|
||||
});
|
||||
|
||||
it('calls .querySelector with the selector string', function () {
|
||||
expect(Document.prototype.querySelector).toHaveBeenCalledWith(this.selector);
|
||||
});
|
||||
|
||||
it('sets the .list property element', function () {
|
||||
expect(this.dropdown.list).toBe(this.element);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('getItems', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { querySelectorAll: () => {} };
|
||||
this.dropdown = { list: this.list };
|
||||
this.nodeList = [];
|
||||
|
||||
spyOn(this.list, 'querySelectorAll').and.returnValue(this.nodeList);
|
||||
|
||||
this.getItems = DropDown.prototype.getItems.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('calls .querySelectorAll with a list item query', function () {
|
||||
expect(this.list.querySelectorAll).toHaveBeenCalledWith('li');
|
||||
});
|
||||
|
||||
it('sets the .items property to the returned list items', function () {
|
||||
expect(this.dropdown.items).toEqual(jasmine.any(Array));
|
||||
});
|
||||
|
||||
it('returns the .items', function () {
|
||||
expect(this.getItems).toEqual(jasmine.any(Array));
|
||||
});
|
||||
});
|
||||
|
||||
describe('initTemplateString', function () {
|
||||
beforeEach(function () {
|
||||
this.items = [{ outerHTML: '<a></a>' }, { outerHTML: '<img>' }];
|
||||
this.dropdown = { items: this.items };
|
||||
|
||||
DropDown.prototype.initTemplateString.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should set .templateString to the last items .outerHTML', function () {
|
||||
expect(this.dropdown.templateString).toBe(this.items[1].outerHTML);
|
||||
});
|
||||
|
||||
it('should not set .templateString to a non-last items .outerHTML', function () {
|
||||
expect(this.dropdown.templateString).not.toBe(this.items[0].outerHTML);
|
||||
});
|
||||
|
||||
describe('if .items is not set', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = { getItems: () => {} };
|
||||
|
||||
spyOn(this.dropdown, 'getItems').and.returnValue([]);
|
||||
|
||||
DropDown.prototype.initTemplateString.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call .getItems', function () {
|
||||
expect(this.dropdown.getItems).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if items array is empty', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = { items: [] };
|
||||
|
||||
DropDown.prototype.initTemplateString.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should set .templateString to an empty string', function () {
|
||||
expect(this.dropdown.templateString).toBe('');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('clickEvent', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { dispatchEvent: () => {} };
|
||||
this.dropdown = { hide: () => {}, list: this.list, addSelectedClass: () => {} };
|
||||
this.event = { preventDefault: () => {}, target: 'target' };
|
||||
this.customEvent = {};
|
||||
this.closestElement = {};
|
||||
|
||||
spyOn(this.dropdown, 'hide');
|
||||
spyOn(this.dropdown, 'addSelectedClass');
|
||||
spyOn(this.list, 'dispatchEvent');
|
||||
spyOn(this.event, 'preventDefault');
|
||||
spyOn(window, 'CustomEvent').and.returnValue(this.customEvent);
|
||||
spyOn(utils, 'closest').and.returnValues(this.closestElement, undefined);
|
||||
|
||||
DropDown.prototype.clickEvent.call(this.dropdown, this.event);
|
||||
});
|
||||
|
||||
it('should call utils.closest', function () {
|
||||
expect(utils.closest).toHaveBeenCalledWith(this.event.target, 'LI');
|
||||
});
|
||||
|
||||
it('should call addSelectedClass', function () {
|
||||
expect(this.dropdown.addSelectedClass).toHaveBeenCalledWith(this.closestElement);
|
||||
})
|
||||
|
||||
it('should call .preventDefault', function () {
|
||||
expect(this.event.preventDefault).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call .hide', function () {
|
||||
expect(this.dropdown.hide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should construct CustomEvent', function () {
|
||||
expect(window.CustomEvent).toHaveBeenCalledWith('click.dl', jasmine.any(Object));
|
||||
});
|
||||
|
||||
it('should call .dispatchEvent with the customEvent', function () {
|
||||
expect(this.list.dispatchEvent).toHaveBeenCalledWith(this.customEvent);
|
||||
});
|
||||
|
||||
describe('if no selected element exists', function () {
|
||||
beforeEach(function () {
|
||||
this.event.preventDefault.calls.reset();
|
||||
this.clickEvent = DropDown.prototype.clickEvent.call(this.dropdown, this.event);
|
||||
});
|
||||
|
||||
it('should return undefined', function () {
|
||||
expect(this.clickEvent).toBe(undefined);
|
||||
});
|
||||
|
||||
it('should return before .preventDefault is called', function () {
|
||||
expect(this.event.preventDefault).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addSelectedClass', function () {
|
||||
beforeEach(function () {
|
||||
this.items = Array(4).forEach((item, i) => {
|
||||
this.items[i] = { classList: { add: () => {} } };
|
||||
spyOn(this.items[i].classList, 'add');
|
||||
});
|
||||
this.selected = { classList: { add: () => {} } };
|
||||
this.dropdown = { removeSelectedClasses: () => {} };
|
||||
|
||||
spyOn(this.dropdown, 'removeSelectedClasses');
|
||||
spyOn(this.selected.classList, 'add');
|
||||
|
||||
DropDown.prototype.addSelectedClass.call(this.dropdown, this.selected);
|
||||
});
|
||||
|
||||
it('should call .removeSelectedClasses', function () {
|
||||
expect(this.dropdown.removeSelectedClasses).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should call .classList.add', function () {
|
||||
expect(this.selected.classList.add).toHaveBeenCalledWith(SELECTED_CLASS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeSelectedClasses', function () {
|
||||
beforeEach(function () {
|
||||
this.items = Array(4);
|
||||
this.items.forEach((item, i) => {
|
||||
this.items[i] = { classList: { add: () => {} } };
|
||||
spyOn(this.items[i].classList, 'add');
|
||||
});
|
||||
this.dropdown = { items: this.items };
|
||||
|
||||
DropDown.prototype.removeSelectedClasses.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call .classList.remove for all items', function () {
|
||||
this.items.forEach((item, i) => {
|
||||
expect(this.items[i].classList.add).toHaveBeenCalledWith(SELECTED_CLASS);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if .items is not set', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = { getItems: () => {} };
|
||||
|
||||
spyOn(this.dropdown, 'getItems').and.returnValue([]);
|
||||
|
||||
DropDown.prototype.removeSelectedClasses.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call .getItems', function () {
|
||||
expect(this.dropdown.getItems).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addEvents', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { addEventListener: () => {} };
|
||||
this.dropdown = { list: this.list, clickEvent: () => {}, eventWrapper: {} };
|
||||
|
||||
spyOn(this.list, 'addEventListener');
|
||||
|
||||
DropDown.prototype.addEvents.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call .addEventListener', function () {
|
||||
expect(this.list.addEventListener).toHaveBeenCalledWith('click', jasmine.any(Function));
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggle', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = { hidden: true, show: () => {}, hide: () => {} };
|
||||
|
||||
spyOn(this.dropdown, 'show');
|
||||
spyOn(this.dropdown, 'hide');
|
||||
|
||||
DropDown.prototype.toggle.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call .show if hidden is true', function () {
|
||||
expect(this.dropdown.show).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('if hidden is false', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = { hidden: false, show: () => {}, hide: () => {} };
|
||||
|
||||
spyOn(this.dropdown, 'show');
|
||||
spyOn(this.dropdown, 'hide');
|
||||
|
||||
DropDown.prototype.toggle.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call .show if hidden is true', function () {
|
||||
expect(this.dropdown.hide).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setData', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = { render: () => {} };
|
||||
this.data = ['data'];
|
||||
|
||||
spyOn(this.dropdown, 'render');
|
||||
|
||||
DropDown.prototype.setData.call(this.dropdown, this.data);
|
||||
});
|
||||
|
||||
it('should set .data', function () {
|
||||
expect(this.dropdown.data).toBe(this.data);
|
||||
});
|
||||
|
||||
it('should call .render with the .data', function () {
|
||||
expect(this.dropdown.render).toHaveBeenCalledWith(this.data);
|
||||
});
|
||||
});
|
||||
|
||||
describe('addData', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = { render: () => {}, data: ['data1'] };
|
||||
this.data = ['data2'];
|
||||
|
||||
spyOn(this.dropdown, 'render');
|
||||
spyOn(Array.prototype, 'concat').and.callThrough();
|
||||
|
||||
DropDown.prototype.addData.call(this.dropdown, this.data);
|
||||
});
|
||||
|
||||
it('should call .concat with data', function () {
|
||||
expect(Array.prototype.concat).toHaveBeenCalledWith(this.data);
|
||||
});
|
||||
|
||||
it('should set .data with concatination', function () {
|
||||
expect(this.dropdown.data).toEqual(['data1', 'data2']);
|
||||
});
|
||||
|
||||
it('should call .render with the .data', function () {
|
||||
expect(this.dropdown.render).toHaveBeenCalledWith(['data1', 'data2']);
|
||||
});
|
||||
|
||||
describe('if .data is undefined', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = { render: () => {}, data: undefined };
|
||||
this.data = ['data2'];
|
||||
|
||||
spyOn(this.dropdown, 'render');
|
||||
|
||||
DropDown.prototype.addData.call(this.dropdown, this.data);
|
||||
});
|
||||
|
||||
it('should set .data with concatination', function () {
|
||||
expect(this.dropdown.data).toEqual(['data2']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('render', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { querySelector: () => {} };
|
||||
this.dropdown = { renderChildren: () => {}, list: this.list };
|
||||
this.renderableList = {};
|
||||
this.data = [0, 1];
|
||||
|
||||
spyOn(this.dropdown, 'renderChildren').and.callFake(data => data);
|
||||
spyOn(this.list, 'querySelector').and.returnValue(this.renderableList);
|
||||
spyOn(this.data, 'map').and.callThrough();
|
||||
|
||||
DropDown.prototype.render.call(this.dropdown, this.data);
|
||||
});
|
||||
|
||||
it('should call .map', function () {
|
||||
expect(this.data.map).toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should call .renderChildren for each data item', function() {
|
||||
expect(this.dropdown.renderChildren.calls.count()).toBe(this.data.length);
|
||||
});
|
||||
|
||||
it('sets the renderableList .innerHTML', function () {
|
||||
expect(this.renderableList.innerHTML).toBe('01');
|
||||
});
|
||||
|
||||
describe('if no data argument is passed' , function () {
|
||||
beforeEach(function () {
|
||||
this.data.map.calls.reset();
|
||||
this.dropdown.renderChildren.calls.reset();
|
||||
|
||||
DropDown.prototype.render.call(this.dropdown, undefined);
|
||||
});
|
||||
|
||||
it('should not call .map', function () {
|
||||
expect(this.data.map).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('should not call .renderChildren', function () {
|
||||
expect(this.dropdown.renderChildren).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe('if no dynamic list is present', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { querySelector: () => {} };
|
||||
this.dropdown = { renderChildren: () => {}, list: this.list };
|
||||
this.data = [0, 1];
|
||||
|
||||
spyOn(this.dropdown, 'renderChildren').and.callFake(data => data);
|
||||
spyOn(this.list, 'querySelector');
|
||||
spyOn(this.data, 'map').and.callThrough();
|
||||
|
||||
DropDown.prototype.render.call(this.dropdown, this.data);
|
||||
});
|
||||
|
||||
it('sets the .list .innerHTML', function () {
|
||||
expect(this.list.innerHTML).toBe('01');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('renderChildren', function () {
|
||||
beforeEach(function () {
|
||||
this.templateString = 'templateString';
|
||||
this.dropdown = { setImagesSrc: () => {}, templateString: this.templateString };
|
||||
this.data = { droplab_hidden: true };
|
||||
this.html = 'html';
|
||||
this.template = { firstChild: { outerHTML: 'outerHTML', style: {} } };
|
||||
|
||||
spyOn(utils, 't').and.returnValue(this.html);
|
||||
spyOn(document, 'createElement').and.returnValue(this.template);
|
||||
spyOn(this.dropdown, 'setImagesSrc');
|
||||
|
||||
this.renderChildren = DropDown.prototype.renderChildren.call(this.dropdown, this.data);
|
||||
});
|
||||
|
||||
it('should call utils.t with .templateString and data', function () {
|
||||
expect(utils.t).toHaveBeenCalledWith(this.templateString, this.data);
|
||||
});
|
||||
|
||||
it('should call document.createElement', function () {
|
||||
expect(document.createElement).toHaveBeenCalledWith('div');
|
||||
});
|
||||
|
||||
it('should set the templates .innerHTML to the HTML', function () {
|
||||
expect(this.template.innerHTML).toBe(this.html);
|
||||
});
|
||||
|
||||
it('should call .setImagesSrc with the template', function () {
|
||||
expect(this.dropdown.setImagesSrc).toHaveBeenCalledWith(this.template);
|
||||
});
|
||||
|
||||
it('should set the template display to none', function () {
|
||||
expect(this.template.firstChild.style.display).toBe('none');
|
||||
});
|
||||
|
||||
it('should return the templates .firstChild.outerHTML', function () {
|
||||
expect(this.renderChildren).toBe(this.template.firstChild.outerHTML);
|
||||
});
|
||||
|
||||
describe('if droplab_hidden is false', function () {
|
||||
beforeEach(function () {
|
||||
this.data = { droplab_hidden: false };
|
||||
this.renderChildren = DropDown.prototype.renderChildren.call(this.dropdown, this.data);
|
||||
});
|
||||
|
||||
it('should set the template display to block', function () {
|
||||
expect(this.template.firstChild.style.display).toBe('block');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setImagesSrc', function () {
|
||||
beforeEach(function () {
|
||||
this.dropdown = {};
|
||||
this.template = { querySelectorAll: () => {} };
|
||||
|
||||
spyOn(this.template, 'querySelectorAll').and.returnValue([]);
|
||||
|
||||
DropDown.prototype.setImagesSrc.call(this.dropdown, this.template);
|
||||
});
|
||||
|
||||
it('should call .querySelectorAll', function () {
|
||||
expect(this.template.querySelectorAll).toHaveBeenCalledWith('img[data-src]');
|
||||
});
|
||||
});
|
||||
|
||||
describe('show', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { style: {} };
|
||||
this.dropdown = { list: this.list, hidden: true };
|
||||
|
||||
DropDown.prototype.show.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('it should set .list display to block', function () {
|
||||
expect(this.list.style.display).toBe('block');
|
||||
});
|
||||
|
||||
it('it should set .hidden to false', function () {
|
||||
expect(this.dropdown.hidden).toBe(false);
|
||||
});
|
||||
|
||||
describe('if .hidden is false', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { style: {} };
|
||||
this.dropdown = { list: this.list, hidden: false };
|
||||
|
||||
this.show = DropDown.prototype.show.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should return undefined', function () {
|
||||
expect(this.show).toEqual(undefined);
|
||||
});
|
||||
|
||||
it('should not set .list display to block', function () {
|
||||
expect(this.list.style.display).not.toEqual('block');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('hide', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { style: {} };
|
||||
this.dropdown = { list: this.list };
|
||||
|
||||
DropDown.prototype.hide.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('it should set .list display to none', function () {
|
||||
expect(this.list.style.display).toBe('none');
|
||||
});
|
||||
|
||||
it('it should set .hidden to true', function () {
|
||||
expect(this.dropdown.hidden).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('toggle', function () {
|
||||
beforeEach(function () {
|
||||
this.hidden = true
|
||||
this.dropdown = { hidden: this.hidden, show: () => {}, hide: () => {} };
|
||||
|
||||
spyOn(this.dropdown, 'show');
|
||||
spyOn(this.dropdown, 'hide');
|
||||
|
||||
DropDown.prototype.toggle.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call .show', function () {
|
||||
expect(this.dropdown.show).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('if .hidden is false', function () {
|
||||
beforeEach(function () {
|
||||
this.hidden = false
|
||||
this.dropdown = { hidden: this.hidden, show: () => {}, hide: () => {} };
|
||||
|
||||
spyOn(this.dropdown, 'show');
|
||||
spyOn(this.dropdown, 'hide');
|
||||
|
||||
DropDown.prototype.toggle.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call .hide', function () {
|
||||
expect(this.dropdown.hide).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('destroy', function () {
|
||||
beforeEach(function () {
|
||||
this.list = { removeEventListener: () => {} };
|
||||
this.eventWrapper = { clickEvent: 'clickEvent' };
|
||||
this.dropdown = { list: this.list, hide: () => {}, eventWrapper: this.eventWrapper };
|
||||
|
||||
spyOn(this.list, 'removeEventListener');
|
||||
spyOn(this.dropdown, 'hide');
|
||||
|
||||
DropDown.prototype.destroy.call(this.dropdown);
|
||||
});
|
||||
|
||||
it('it should call .hide', function () {
|
||||
expect(this.dropdown.hide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('it should call .removeEventListener', function () {
|
||||
expect(this.list.removeEventListener).toHaveBeenCalledWith('click', this.eventWrapper.clickEvent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import Hook from '~/droplab/hook';
|
||||
import * as dropdownSrc from '~/droplab/drop_down';
|
||||
|
||||
describe('Hook', function () {
|
||||
describe('class constructor', function () {
|
||||
beforeEach(function () {
|
||||
this.trigger = { id: 'id' };
|
||||
this.list = {};
|
||||
this.plugins = {};
|
||||
this.config = {};
|
||||
this.dropdown = {};
|
||||
|
||||
spyOn(dropdownSrc, 'default').and.returnValue(this.dropdown);
|
||||
|
||||
this.hook = new Hook(this.trigger, this.list, this.plugins, this.config);
|
||||
});
|
||||
|
||||
it('should set .trigger', function () {
|
||||
expect(this.hook.trigger).toBe(this.trigger);
|
||||
});
|
||||
|
||||
it('should set .list', function () {
|
||||
expect(this.hook.list).toBe(this.dropdown);
|
||||
});
|
||||
|
||||
it('should call DropDown constructor', function () {
|
||||
expect(dropdownSrc.default).toHaveBeenCalledWith(this.list);
|
||||
});
|
||||
|
||||
it('should set .type', function () {
|
||||
expect(this.hook.type).toBe('Hook');
|
||||
});
|
||||
|
||||
it('should set .event', function () {
|
||||
expect(this.hook.event).toBe('click');
|
||||
});
|
||||
|
||||
it('should set .plugins', function () {
|
||||
expect(this.hook.plugins).toBe(this.plugins);
|
||||
});
|
||||
|
||||
it('should set .config', function () {
|
||||
expect(this.hook.config).toBe(this.config);
|
||||
});
|
||||
|
||||
it('should set .id', function () {
|
||||
expect(this.hook.id).toBe(this.trigger.id);
|
||||
});
|
||||
|
||||
describe('if config argument is undefined', function () {
|
||||
beforeEach(function () {
|
||||
this.config = undefined;
|
||||
|
||||
this.hook = new Hook(this.trigger, this.list, this.plugins, this.config);
|
||||
});
|
||||
|
||||
it('should set .config to an empty object', function () {
|
||||
expect(this.hook.config).toEqual({});
|
||||
});
|
||||
});
|
||||
|
||||
describe('if plugins argument is undefined', function () {
|
||||
beforeEach(function () {
|
||||
this.plugins = undefined;
|
||||
|
||||
this.hook = new Hook(this.trigger, this.list, this.plugins, this.config);
|
||||
});
|
||||
|
||||
it('should set .plugins to an empty array', function () {
|
||||
expect(this.hook.plugins).toEqual([]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('addEvents', function () {
|
||||
it('should exist', function () {
|
||||
expect(Hook.prototype.hasOwnProperty('addEvents')).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -0,0 +1,246 @@
|
|||
/* eslint-disable */
|
||||
|
||||
import InputSetter from '~/droplab/plugins/input_setter';
|
||||
|
||||
describe('InputSetter', function () {
|
||||
describe('init', function () {
|
||||
beforeEach(function () {
|
||||
this.config = { InputSetter: {} };
|
||||
this.hook = { config: this.config };
|
||||
this.inputSetter = jasmine.createSpyObj('inputSetter', ['addEvents']);
|
||||
|
||||
InputSetter.init.call(this.inputSetter, this.hook);
|
||||
});
|
||||
|
||||
it('should set .hook', function () {
|
||||
expect(this.inputSetter.hook).toBe(this.hook);
|
||||
});
|
||||
|
||||
it('should set .config', function () {
|
||||
expect(this.inputSetter.config).toBe(this.config.InputSetter);
|
||||
});
|
||||
|
||||
it('should set .eventWrapper', function () {
|
||||
expect(this.inputSetter.eventWrapper).toEqual({});
|
||||
});
|
||||
|
||||
it('should call .addEvents', function () {
|
||||
expect(this.inputSetter.addEvents).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe('if config.InputSetter is not set', function () {
|
||||
beforeEach(function () {
|
||||
this.config = { InputSetter: undefined };
|
||||
this.hook = { config: this.config };
|
||||
|
||||
InputSetter.init.call(this.inputSetter, this.hook);
|
||||
});
|
||||
|
||||
it('should set .config to an empty object', function () {
|
||||
expect(this.inputSetter.config).toEqual({});
|
||||
});
|
||||
|
||||
it('should set hook.config to an empty object', function () {
|
||||
expect(this.hook.config.InputSetter).toEqual({});
|
||||
});
|
||||
})
|
||||
});
|
||||
|
||||
describe('addEvents', function () {
|
||||
beforeEach(function () {
|
||||
this.hook = { list: { list: jasmine.createSpyObj('list', ['addEventListener']) } };
|
||||
this.inputSetter = { eventWrapper: {}, hook: this.hook, setInputs: () => {} };
|
||||
|
||||
InputSetter.addEvents.call(this.inputSetter);
|
||||
});
|
||||
|
||||
it('should set .eventWrapper.setInputs', function () {
|
||||
expect(this.inputSetter.eventWrapper.setInputs).toEqual(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it('should call .addEventListener', function () {
|
||||
expect(this.hook.list.list.addEventListener)
|
||||
.toHaveBeenCalledWith('click.dl', this.inputSetter.eventWrapper.setInputs);
|
||||
});
|
||||
});
|
||||
|
||||
describe('removeEvents', function () {
|
||||
beforeEach(function () {
|
||||
this.hook = { list: { list: jasmine.createSpyObj('list', ['removeEventListener']) } };
|
||||
this.eventWrapper = jasmine.createSpyObj('eventWrapper', ['setInputs']);
|
||||
this.inputSetter = { eventWrapper: this.eventWrapper, hook: this.hook };
|
||||
|
||||
InputSetter.removeEvents.call(this.inputSetter);
|
||||
});
|
||||
|
||||
it('should call .removeEventListener', function () {
|
||||
expect(this.hook.list.list.removeEventListener)
|
||||
.toHaveBeenCalledWith('click.dl', this.eventWrapper.setInputs);
|
||||
});
|
||||
});
|
||||
|
||||
describe('setInputs', function () {
|
||||
beforeEach(function () {
|
||||
this.event = { detail: { selected: {} } };
|
||||
this.config = [0, 1];
|
||||
this.inputSetter = { config: this.config, setInput: () => {} };
|
||||
|
||||
spyOn(this.inputSetter, 'setInput');
|
||||
|
||||
InputSetter.setInputs.call(this.inputSetter, this.event);
|
||||
});
|
||||
|
||||
it('should call .setInput for each config element', function () {
|
||||
const allArgs = this.inputSetter.setInput.calls.allArgs();
|
||||
|
||||
expect(allArgs.length).toEqual(2);
|
||||
|
||||
allArgs.forEach((args, i) => {
|
||||
expect(args[0]).toBe(this.config[i]);
|
||||
expect(args[1]).toBe(this.event.detail.selected);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if config isnt an array', function () {
|
||||
beforeEach(function () {
|
||||
this.inputSetter = { config: {}, setInput: () => {} };
|
||||
|
||||
InputSetter.setInputs.call(this.inputSetter, this.event);
|
||||
});
|
||||
|
||||
it('should set .config to an array with .config as the first element', function () {
|
||||
expect(this.inputSetter.config).toEqual([{}]);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('setInput', function () {
|
||||
beforeEach(function () {
|
||||
this.selectedItem = { getAttribute: () => {} };
|
||||
this.input = { value: 'oldValue', tagName: 'INPUT', hasAttribute: () => {} };
|
||||
this.config = { valueAttribute: {}, input: this.input };
|
||||
this.inputSetter = { hook: { trigger: {} } };
|
||||
this.newValue = 'newValue';
|
||||
|
||||
spyOn(this.selectedItem, 'getAttribute').and.returnValue(this.newValue);
|
||||
spyOn(this.input, 'hasAttribute').and.returnValue(false);
|
||||
|
||||
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
|
||||
});
|
||||
|
||||
it('should call .getAttribute', function () {
|
||||
expect(this.selectedItem.getAttribute).toHaveBeenCalledWith(this.config.valueAttribute);
|
||||
});
|
||||
|
||||
it('should call .hasAttribute', function () {
|
||||
expect(this.input.hasAttribute).toHaveBeenCalledWith(undefined);
|
||||
});
|
||||
|
||||
it('should set the value of the input', function () {
|
||||
expect(this.input.value).toBe(this.newValue);
|
||||
});
|
||||
|
||||
describe('if there is no newValue', function () {
|
||||
beforeEach(function () {
|
||||
this.newValue = '';
|
||||
this.inputSetter = { hook: { trigger: {} } };
|
||||
this.config = { valueAttribute: {}, input: this.input };
|
||||
this.input = { value: 'oldValue', tagName: 'INPUT' };
|
||||
this.selectedItem = { getAttribute: () => {} };
|
||||
|
||||
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
|
||||
});
|
||||
|
||||
it('should not set the value of the input', function () {
|
||||
expect(this.input.value).toBe('oldValue');
|
||||
})
|
||||
});
|
||||
|
||||
describe('if no config.input is provided', function () {
|
||||
beforeEach(function () {
|
||||
this.config = { valueAttribute: {} };
|
||||
this.trigger = { value: 'oldValue', tagName: 'INPUT', hasAttribute: () => {} };
|
||||
this.inputSetter = { hook: { trigger: this.trigger } };
|
||||
|
||||
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
|
||||
});
|
||||
|
||||
it('should set the value of the hook.trigger', function () {
|
||||
expect(this.trigger.value).toBe(this.newValue);
|
||||
});
|
||||
});
|
||||
|
||||
describe('if the input tag is not INPUT', function () {
|
||||
beforeEach(function () {
|
||||
this.input = { textContent: 'oldValue', tagName: 'SPAN', hasAttribute: () => {} };
|
||||
this.config = { valueAttribute: {}, input: this.input };
|
||||
|
||||
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
|
||||
});
|
||||
|
||||
it('should set the textContent of the input', function () {
|
||||
expect(this.input.textContent).toBe(this.newValue);
|
||||
});
|
||||
|
||||
describe('if there is no new value', function () {
|
||||
beforeEach(function () {
|
||||
this.selectedItem = { getAttribute: () => {} };
|
||||
this.input = { textContent: 'oldValue', tagName: 'INPUT', hasAttribute: () => {} };
|
||||
this.config = { valueAttribute: {}, input: this.input };
|
||||
this.inputSetter = { hook: { trigger: {} } };
|
||||
this.newValue = 'newValue';
|
||||
|
||||
spyOn(this.selectedItem, 'getAttribute').and.returnValue(this.newValue);
|
||||
|
||||
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
|
||||
});
|
||||
|
||||
it('should not set the value of the input', function () {
|
||||
expect(this.input.textContent).toBe('oldValue');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('if there is an inputAttribute', function () {
|
||||
beforeEach(function () {
|
||||
this.selectedItem = { getAttribute: () => {} };
|
||||
this.input = { id: 'oldValue', hasAttribute: () => {}, setAttribute: () => {} };
|
||||
this.inputSetter = { hook: { trigger: {} } };
|
||||
this.newValue = 'newValue';
|
||||
this.inputAttribute = 'id';
|
||||
this.config = {
|
||||
valueAttribute: {},
|
||||
input: this.input,
|
||||
inputAttribute: this.inputAttribute,
|
||||
};
|
||||
|
||||
spyOn(this.selectedItem, 'getAttribute').and.returnValue(this.newValue);
|
||||
spyOn(this.input, 'hasAttribute').and.returnValue(true);
|
||||
spyOn(this.input, 'setAttribute');
|
||||
|
||||
InputSetter.setInput.call(this.inputSetter, this.config, this.selectedItem);
|
||||
});
|
||||
|
||||
it('should call setAttribute', function () {
|
||||
expect(this.input.setAttribute).toHaveBeenCalledWith(this.inputAttribute, this.newValue);
|
||||
});
|
||||
|
||||
it('should not set the value or textContent of the input', function () {
|
||||
expect(this.input.value).not.toBe('newValue');
|
||||
expect(this.input.textContent).not.toBe('newValue');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('destroy', function () {
|
||||
beforeEach(function () {
|
||||
this.inputSetter = jasmine.createSpyObj('inputSetter', ['removeEvents']);
|
||||
|
||||
InputSetter.destroy.call(this.inputSetter);
|
||||
});
|
||||
|
||||
it('should call .removeEvents', function () {
|
||||
expect(this.inputSetter.removeEvents).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
@ -33,7 +33,7 @@ require('~/filtered_search/dropdown_user');
|
|||
});
|
||||
});
|
||||
|
||||
describe('config droplabAjaxFilter\'s endpoint', () => {
|
||||
describe('config AjaxFilter\'s endpoint', () => {
|
||||
beforeEach(() => {
|
||||
spyOn(gl.DropdownUser.prototype, 'bindEvents').and.callFake(() => {});
|
||||
spyOn(gl.DropdownUser.prototype, 'getProjectId').and.callFake(() => {});
|
||||
|
|
@ -45,13 +45,13 @@ require('~/filtered_search/dropdown_user');
|
|||
};
|
||||
const dropdown = new gl.DropdownUser();
|
||||
|
||||
expect(dropdown.config.droplabAjaxFilter.endpoint).toBe('/autocomplete/users.json');
|
||||
expect(dropdown.config.AjaxFilter.endpoint).toBe('/autocomplete/users.json');
|
||||
});
|
||||
|
||||
it('should return endpoint when relative_url_root is undefined', () => {
|
||||
const dropdown = new gl.DropdownUser();
|
||||
|
||||
expect(dropdown.config.droplabAjaxFilter.endpoint).toBe('/autocomplete/users.json');
|
||||
expect(dropdown.config.AjaxFilter.endpoint).toBe('/autocomplete/users.json');
|
||||
});
|
||||
|
||||
it('should return endpoint with relative url when available', () => {
|
||||
|
|
@ -60,7 +60,7 @@ require('~/filtered_search/dropdown_user');
|
|||
};
|
||||
const dropdown = new gl.DropdownUser();
|
||||
|
||||
expect(dropdown.config.droplabAjaxFilter.endpoint).toBe('/gitlab_directory/autocomplete/users.json');
|
||||
expect(dropdown.config.AjaxFilter.endpoint).toBe('/gitlab_directory/autocomplete/users.json');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
|
|
|||
Loading…
Reference in New Issue