Commit 367a1588 authored by Clement Ho's avatar Clement Ho

Update droplab

parent ceb79e3c
...@@ -53,6 +53,7 @@ Object.assign(DropDown.prototype, { ...@@ -53,6 +53,7 @@ Object.assign(DropDown.prototype, {
this.list.addEventListener('click', function(e) { this.list.addEventListener('click', function(e) {
// climb up the tree to find the LI // climb up the tree to find the LI
var selected = utils.closest(e.target, 'LI'); var selected = utils.closest(e.target, 'LI');
if(selected) { if(selected) {
e.preventDefault(); e.preventDefault();
self.hide(); self.hide();
...@@ -158,17 +159,22 @@ require('./window')(function(w){ ...@@ -158,17 +159,22 @@ require('./window')(function(w){
this.ready = false; this.ready = false;
this.hooks = []; this.hooks = [];
this.queuedData = []; this.queuedData = [];
this.plugins = [];
this.config = {}; this.config = {};
this.loadWrapper;
if(typeof hook !== 'undefined'){ if(typeof hook !== 'undefined'){
this.addHook(hook); this.addHook(hook);
} }
this.addEvents();
}; };
Object.assign(DropLab.prototype, { Object.assign(DropLab.prototype, {
plugin: function (plugin) { load: function() {
this.plugins.push(plugin) this.loadWrapper();
},
loadWrapper: function(){
var dropdownTriggers = [].slice.apply(document.querySelectorAll('['+DATA_TRIGGER+']'));
this.addHooks(dropdownTriggers).init();
}, },
addData: function () { addData: function () {
...@@ -181,6 +187,14 @@ require('./window')(function(w){ ...@@ -181,6 +187,14 @@ require('./window')(function(w){
this.applyArgs(args, '_setData'); this.applyArgs(args, '_setData');
}, },
destroy: function() {
this.hooks.forEach(function(h){
h.destroy();
});
this.hooks = [];
this.removeEvents();
},
applyArgs: function(args, methodName) { applyArgs: function(args, methodName) {
if(this.ready) { if(this.ready) {
this[methodName].apply(this, args); this[methodName].apply(this, args);
...@@ -210,7 +224,7 @@ require('./window')(function(w){ ...@@ -210,7 +224,7 @@ require('./window')(function(w){
addEvents: function() { addEvents: function() {
var self = this; var self = this;
window.addEventListener('click', function(e){ this.windowClickedWrapper = function(e){
var thisTag = e.target; var thisTag = e.target;
if(thisTag.tagName === 'LI' || thisTag.tagName === 'A' if(thisTag.tagName === 'LI' || thisTag.tagName === 'A'
|| thisTag.tagName === 'BUTTON'){ || thisTag.tagName === 'BUTTON'){
...@@ -222,10 +236,16 @@ require('./window')(function(w){ ...@@ -222,10 +236,16 @@ require('./window')(function(w){
self.hooks.forEach(function(hook) { self.hooks.forEach(function(hook) {
hook.list.hide(); hook.list.hide();
}); });
}); }.bind(this);
w.addEventListener('click', this.windowClickedWrapper);
},
removeEvents: function(){
w.removeEventListener('click', this.windowClickedWrapper);
w.removeEventListener('load', this.loadWrapper);
}, },
changeHookList: function(trigger, list) { changeHookList: function(trigger, list, plugins, config) {
trigger = document.querySelector('[data-id="'+trigger+'"]'); trigger = document.querySelector('[data-id="'+trigger+'"]');
list = document.querySelector(list); list = document.querySelector(list);
this.hooks.every(function(hook, i) { this.hooks.every(function(hook, i) {
...@@ -234,19 +254,16 @@ require('./window')(function(w){ ...@@ -234,19 +254,16 @@ require('./window')(function(w){
hook.list.list.innerHTML = hook.list.initialState; hook.list.list.innerHTML = hook.list.initialState;
hook.list.hide(); hook.list.hide();
hook.trigger.removeEventListener('mousedown', hook.events.mousedown); hook.destroy();
hook.trigger.removeEventListener('input', hook.events.input);
hook.trigger.removeEventListener('keyup', hook.events.keyup);
hook.trigger.removeEventListener('keydown', hook.events.keydown);
this.hooks.splice(i, 1); this.hooks.splice(i, 1);
this.addHook(trigger, list); this.addHook(trigger, list, plugins, config);
return false; return false;
} }
return true return true
}.bind(this)); }.bind(this));
}, },
addHook: function(hook, list) { addHook: function(hook, list, plugins, config) {
if(!(hook instanceof HTMLElement) && typeof hook === 'string'){ if(!(hook instanceof HTMLElement) && typeof hook === 'string'){
hook = document.querySelector(hook); hook = document.querySelector(hook);
} }
...@@ -256,17 +273,17 @@ require('./window')(function(w){ ...@@ -256,17 +273,17 @@ require('./window')(function(w){
if(hook) { if(hook) {
if(hook.tagName === 'A' || hook.tagName === 'BUTTON') { if(hook.tagName === 'A' || hook.tagName === 'BUTTON') {
this.hooks.push(new HookButton(hook, list)); this.hooks.push(new HookButton(hook, list, plugins, config));
} else if(hook.tagName === 'INPUT') { } else if(hook.tagName === 'INPUT') {
this.hooks.push(new HookInput(hook, list)); this.hooks.push(new HookInput(hook, list, plugins, config));
} }
} }
return this; return this;
}, },
addHooks: function(hooks) { addHooks: function(hooks, plugins, config) {
hooks.forEach(function(hook) { hooks.forEach(function(hook) {
this.addHook(hook, null); this.addHook(hook, null, plugins, config);
}.bind(this)); }.bind(this));
return this; return this;
}, },
...@@ -276,9 +293,7 @@ require('./window')(function(w){ ...@@ -276,9 +293,7 @@ require('./window')(function(w){
}, },
init: function () { init: function () {
this.plugins.forEach(function(plugin) { this.addEvents();
plugin(DropLab);
})
var readyEvent = new CustomEvent('ready.dl', { var readyEvent = new CustomEvent('ready.dl', {
detail: { detail: {
dropdown: this, dropdown: this,
...@@ -301,15 +316,18 @@ require('./window')(function(w){ ...@@ -301,15 +316,18 @@ require('./window')(function(w){
},{"./constants":1,"./custom_event_polyfill":2,"./hook_button":6,"./hook_input":7,"./utils":10,"./window":11}],5:[function(require,module,exports){ },{"./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 DropDown = require('./dropdown');
var Hook = function(trigger, list){ var Hook = function(trigger, list, plugins, config){
this.trigger = trigger; this.trigger = trigger;
this.list = new DropDown(list); this.list = new DropDown(list);
this.type = 'Hook'; this.type = 'Hook';
this.event = 'click'; this.event = 'click';
this.plugins = plugins || [];
this.config = config || {};
this.id = trigger.dataset.id; this.id = trigger.dataset.id;
}; };
Object.assign(Hook.prototype, { Object.assign(Hook.prototype, {
addEvents: function(){}, addEvents: function(){},
constructor: Hook, constructor: Hook,
...@@ -321,31 +339,61 @@ module.exports = Hook; ...@@ -321,31 +339,61 @@ module.exports = Hook;
var CustomEvent = require('./custom_event_polyfill'); var CustomEvent = require('./custom_event_polyfill');
var Hook = require('./hook'); var Hook = require('./hook');
var HookButton = function(trigger, list) { var HookButton = function(trigger, list, plugins, config) {
Hook.call(this, trigger, list); Hook.call(this, trigger, list, plugins, config);
this.type = 'button'; this.type = 'button';
this.event = 'click'; this.event = 'click';
this.addEvents(); this.addEvents();
this.addPlugins();
}; };
HookButton.prototype = Object.create(Hook.prototype); HookButton.prototype = Object.create(Hook.prototype);
Object.assign(HookButton.prototype, { Object.assign(HookButton.prototype, {
addPlugins: function() {
this.plugins.forEach(function(plugin) {
plugin.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(){ addEvents: function(){
var self = this; this.clickedWrapper = this.clicked.bind(this);
this.trigger.addEventListener('click', function(e){ this.trigger.addEventListener('click', this.clickedWrapper);
var buttonEvent = new CustomEvent('click.dl', { },
detail: {
hook: self, removeEvents: function(){
}, this.trigger.removeEventListener('click', this.clickedWrapper);
bubbles: true, },
cancelable: true
}); restoreInitialState: function() {
self.list.show(); this.list.list.innerHTML = this.list.initialState;
e.target.dispatchEvent(buttonEvent); },
removePlugins: function() {
this.plugins.forEach(function(plugin) {
plugin.destroy();
}); });
}, },
destroy: function() {
this.restoreInitialState();
this.removeEvents();
this.removePlugins();
},
constructor: HookButton, constructor: HookButton,
}); });
...@@ -356,18 +404,26 @@ module.exports = HookButton; ...@@ -356,18 +404,26 @@ module.exports = HookButton;
var CustomEvent = require('./custom_event_polyfill'); var CustomEvent = require('./custom_event_polyfill');
var Hook = require('./hook'); var Hook = require('./hook');
var HookInput = function(trigger, list) { var HookInput = function(trigger, list, plugins, config) {
Hook.call(this, trigger, list); Hook.call(this, trigger, list, plugins, config);
this.type = 'input'; this.type = 'input';
this.event = 'input'; this.event = 'input';
this.addPlugins();
this.addEvents(); this.addEvents();
}; };
Object.assign(HookInput.prototype, { Object.assign(HookInput.prototype, {
addPlugins: function() {
var self = this;
this.plugins.forEach(function(plugin) {
plugin.init(self);
});
},
addEvents: function(){ addEvents: function(){
var self = this; var self = this;
function mousedown(e) { this.mousedown = function mousedown(e) {
var mouseEvent = new CustomEvent('mousedown.dl', { var mouseEvent = new CustomEvent('mousedown.dl', {
detail: { detail: {
hook: self, hook: self,
...@@ -379,7 +435,7 @@ Object.assign(HookInput.prototype, { ...@@ -379,7 +435,7 @@ Object.assign(HookInput.prototype, {
e.target.dispatchEvent(mouseEvent); e.target.dispatchEvent(mouseEvent);
} }
function input(e) { this.input = function input(e) {
var inputEvent = new CustomEvent('input.dl', { var inputEvent = new CustomEvent('input.dl', {
detail: { detail: {
hook: self, hook: self,
...@@ -392,11 +448,11 @@ Object.assign(HookInput.prototype, { ...@@ -392,11 +448,11 @@ Object.assign(HookInput.prototype, {
self.list.show(); self.list.show();
} }
function keyup(e) { this.keyup = function keyup(e) {
keyEvent(e, 'keyup.dl'); keyEvent(e, 'keyup.dl');
} }
function keydown(e) { this.keydown = function keydown(e) {
keyEvent(e, 'keydown.dl'); keyEvent(e, 'keydown.dl');
} }
...@@ -416,15 +472,38 @@ Object.assign(HookInput.prototype, { ...@@ -416,15 +472,38 @@ Object.assign(HookInput.prototype, {
} }
this.events = this.events || {}; this.events = this.events || {};
this.events.mousedown = mousedown; this.events.mousedown = this.mousedown;
this.events.input = input; this.events.input = this.input;
this.events.keyup = keyup; this.events.keyup = this.keyup;
this.events.keydown = keydown; this.events.keydown = this.keydown;
this.trigger.addEventListener('mousedown', mousedown); this.trigger.addEventListener('mousedown', this.mousedown);
this.trigger.addEventListener('input', input); this.trigger.addEventListener('input', this.input);
this.trigger.addEventListener('keyup', keyup); this.trigger.addEventListener('keyup', this.keyup);
this.trigger.addEventListener('keydown', keydown); this.trigger.addEventListener('keydown', this.keydown);
}, },
removeEvents: function(){
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() {
this.plugins.forEach(function(plugin) {
plugin.destroy();
});
},
destroy: function() {
this.restoreInitialState();
this.removeEvents();
this.removePlugins();
}
}); });
module.exports = HookInput; module.exports = HookInput;
...@@ -433,21 +512,14 @@ module.exports = HookInput; ...@@ -433,21 +512,14 @@ module.exports = HookInput;
var DropLab = require('./droplab')(); var DropLab = require('./droplab')();
var DATA_TRIGGER = require('./constants').DATA_TRIGGER; var DATA_TRIGGER = require('./constants').DATA_TRIGGER;
var keyboard = require('./keyboard')(); var keyboard = require('./keyboard')();
var setup = function() { var setup = function() {
var droplab = DropLab(); window.DropLab = DropLab;
require('./window')(function(w) {
w.addEventListener('load', function() {
var dropdownTriggers = [].slice.apply(document.querySelectorAll('['+DATA_TRIGGER+']'));
droplab.addHooks(dropdownTriggers).init();
});
});
return droplab;
}; };
module.exports = setup(); module.exports = setup();
},{"./constants":1,"./droplab":4,"./keyboard":9,"./window":11}],9:[function(require,module,exports){ },{"./constants":1,"./droplab":4,"./keyboard":9}],9:[function(require,module,exports){
require('./window')(function(w){ require('./window')(function(w){
module.exports = function(){ module.exports = function(){
var currentKey; var currentKey;
...@@ -557,7 +629,7 @@ var camelize = function(str) { ...@@ -557,7 +629,7 @@ var camelize = function(str) {
}; };
var closest = function(thisTag, stopTag) { var closest = function(thisTag, stopTag) {
while(thisTag !== null && thisTag.tagName !== stopTag && thisTag.tagName !== 'HTML'){ while(thisTag.tagName !== stopTag && thisTag.tagName !== 'HTML'){
thisTag = thisTag.parentNode; thisTag = thisTag.parentNode;
} }
return thisTag; return thisTag;
......
/* eslint-disable */ /* 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){ (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 */ /* global droplab */
droplab.plugin(function init(DropLab) {
var _addData = DropLab.prototype.addData;
var _setData = DropLab.prototype.setData;
var _loadUrlData = function(url) { require('../window')(function(w){
return new Promise(function(resolve, reject) { w.droplabAjax = {
var xhr = new XMLHttpRequest; _loadUrlData: function _loadUrlData(url) {
xhr.open('GET', url, true); return new Promise(function(resolve, reject) {
xhr.onreadystatechange = function () { var xhr = new XMLHttpRequest;
if(xhr.readyState === XMLHttpRequest.DONE) { xhr.open('GET', url, true);
if (xhr.status === 200) { xhr.onreadystatechange = function () {
var data = JSON.parse(xhr.responseText); if(xhr.readyState === XMLHttpRequest.DONE) {
return resolve(data); if (xhr.status === 200) {
} else { var data = JSON.parse(xhr.responseText);
return reject([xhr.responseText, xhr.status]); return resolve(data);
} else {
return reject([xhr.responseText, xhr.status]);
}
} }
} };
}; xhr.send();
xhr.send(); });
});
};
Object.assign(DropLab.prototype, {
addData: function(trigger, data) {
this.processData(trigger, data, _addData);
},
setData: function(trigger, data) {
this.processData(trigger, data, _setData);
}, },
processData: function(trigger, data, methodName) {
var _this = this; init: function init(hook) {
if('string' === typeof data) { var config = hook.config.droplabAjax;
_loadUrlData(data).then(function(d) {
methodName.call(_this, trigger, d); if (!config || !config.endpoint || !config.method) {
}).catch(function(e) { return;
if(e.message)
console.error(e.message, e.stack); // eslint-disable-line no-console
else
console.error(e); // eslint-disable-line no-console
})
} else {
methodName.apply(this, arguments);
} }
if (config.method !== 'setData' && config.method !== 'addData') {
return;
}
this._loadUrlData(config.endpoint).then(function(d) {
hook.list[config.method].call(hook.list, d);
}).catch(function(e) {
if(e.message) {
console.error(e.message, e.stack); // eslint-disable-line no-console
} else {
console.error(e); // eslint-disable-line no-console
}
});
}, },
});
destroy: function() {
}
};
}); });
},{"../window":2}],2:[function(require,module,exports){
module.exports = function(callback) {
return (function() {
callback(this);
}).call(null);
};
},{}]},{},[1])(1) },{}]},{},[1])(1)
}); });
\ No newline at end of file
/* eslint-disable */ /* 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){ (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 */ /* global droplab */
droplab.plugin(function init(DropLab) {
var keydown = function keydown(e) {
var list = e.detail.hook.list;
var data = list.data;
var value = e.detail.hook.trigger.value.toLowerCase();
var config = droplab.config[e.detail.hook.id];
var matches = [];
// will only work on dynamically set data
// and if a config text property is set
if(!data || (!config.hasOwnProperty('text') && !config.hasOwnProperty('filter'))){
return;
}
var filterFunction = function(o){ require('../window')(function(w){
// cheap string search w.droplabFilter = {
o.droplab_hidden = o[config.text].toLowerCase().indexOf(value) === -1;
return o;
};
if (config.hasOwnProperty('filter') && config.filter !== undefined) { keydownWrapper: function(e){
filterFunction = config.filter; 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;
};
}
matches = data.map(function(o) {
return filterFunction(o, value);
});
list.render(matches);
},
init: function init(hookInput) {
var config = hookInput.config.droplabFilter;
matches = data.map(function(o) { if (!config || (!config.template && !config.filterFunction)) {
return filterFunction(o, value); return;
}); }
list.render(matches);
} this.hookInput = hookInput;
window.addEventListener('keyup.dl', keydown); this.hookInput.trigger.addEventListener('keyup.dl', this.keydownWrapper);
},
destroy: function destroy(){
this.hookInput.trigger.removeEventListener('keyup.dl', this.keydownWrapper);
}
};
}); });
},{"../window":2}],2:[function(require,module,exports){
module.exports = function(callback) {
return (function() {
callback(this);
}).call(null);
};
},{}]},{},[1])(1) },{}]},{},[1])(1)
}); });
\ No newline at end of file
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
((global) => { ((global) => {
class DropdownAssignee extends gl.FilteredSearchDropdown { class DropdownAssignee extends gl.FilteredSearchDropdown {
constructor(dropdown, input) { constructor(droplab, dropdown, input) {
super(dropdown, input); super(droplab, dropdown, input);
this.listId = 'js-dropdown-assignee'; this.listId = 'js-dropdown-assignee';
} }
...@@ -20,8 +20,13 @@ ...@@ -20,8 +20,13 @@
} }
renderContent() { renderContent() {
super.renderContent(); // TODO: Pass elements instead of querySelectors
droplab.setData(this.hookId, '/autocomplete/users.json?search=&per_page=20&active=true&project_id=2&group_id=&skip_ldap=&todo_filter=&todo_state_filter=&current_user=true&push_code_to_protected_branches=&author_id=&skip_users='); this.droplab.changeHookList(this.hookId, '#js-dropdown-assignee', [droplabAjax], {
droplabAjax: {
endpoint: '/autocomplete/users.json?search=&per_page=20&active=true&project_id=2&group_id=&skip_ldap=&todo_filter=&todo_state_filter=&current_user=true&push_code_to_protected_branches=&author_id=&skip_users=',
method: 'setData',
}
});
} }
filterMethod(item, query) { filterMethod(item, query) {
......
...@@ -3,8 +3,8 @@ ...@@ -3,8 +3,8 @@
((global) => { ((global) => {
class DropdownAuthor extends gl.FilteredSearchDropdown { class DropdownAuthor extends gl.FilteredSearchDropdown {
constructor(dropdown, input) { constructor(droplab, dropdown, input) {
super(dropdown, input); super(droplab, dropdown, input);
this.listId = 'js-dropdown-author'; this.listId = 'js-dropdown-author';
} }
...@@ -16,8 +16,13 @@ ...@@ -16,8 +16,13 @@
} }
renderContent() { renderContent() {
super.renderContent(); // TODO: Pass elements instead of querySelectors
droplab.setData(this.hookId, '/autocomplete/users.json?search=&per_page=20&active=true&project_id=2&group_id=&skip_ldap=&todo_filter=&todo_state_filter=&current_user=true&push_code_to_protected_branches=&author_id=&skip_users='); this.droplab.changeHookList(this.hookId, '#js-dropdown-author', [droplabAjax], {
droplabAjax: {
endpoint: '/autocomplete/users.json?search=&per_page=20&active=true&project_id=2&group_id=&skip_ldap=&todo_filter=&todo_state_filter=&current_user=true&push_code_to_protected_branches=&author_id=&skip_users=',
method: 'setData',
}
});
} }
filterMethod(item, query) { filterMethod(item, query) {
......
...@@ -21,10 +21,9 @@ ...@@ -21,10 +21,9 @@
}]; }];
class DropdownHint extends gl.FilteredSearchDropdown { class DropdownHint extends gl.FilteredSearchDropdown {
constructor(dropdown, input, filterKeyword) { constructor(droplab, dropdown, input) {
super(dropdown, input); super(droplab, dropdown, input);
this.listId = 'js-dropdown-hint'; this.listId = 'js-dropdown-hint';
this.filterKeyword = filterKeyword;
} }
itemClicked(e) { itemClicked(e) {
...@@ -39,8 +38,13 @@ ...@@ -39,8 +38,13 @@
} }
renderContent() { renderContent() {
super.renderContent(); this.droplab.changeHookList(this.hookId, '#js-dropdown-hint', [droplabFilter], {
droplab.setData(this.hookId, dropdownData); droplabFilter: {
template: 'hint',
filterFunction: this.filterMethod,
}
});
this.droplab.setData(this.hookId, dropdownData);
} }
filterMethod(item, query) { filterMethod(item, query) {
...@@ -54,6 +58,14 @@ ...@@ -54,6 +58,14 @@
return item; return item;
} }
configure() {
this.droplab.addHook(this.input, this.dropdown, [droplabFilter], {
droplabFilter: {
template: 'hint',
}
}).init();
}
} }
global.DropdownHint = DropdownHint; global.DropdownHint = DropdownHint;
......
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
((global) => { ((global) => {
class DropdownLabel extends gl.FilteredSearchDropdown { class DropdownLabel extends gl.FilteredSearchDropdown {
constructor(dropdown, input) { constructor(droplab, dropdown, input) {
super(dropdown, input); super(droplab, dropdown, input);
this.listId = 'js-dropdown-label'; this.listId = 'js-dropdown-label';
this.filterSymbol = '~';
} }
itemClicked(e) { itemClicked(e) {
...@@ -21,20 +22,17 @@ ...@@ -21,20 +22,17 @@
} }
renderContent() { renderContent() {
super.renderContent(); // TODO: Pass elements instead of querySelectors
droplab.setData(this.hookId, 'labels.json'); // TODO: Don't bind filterWithSymbol to (this), just pass the symbol
} this.droplab.changeHookList(this.hookId, '#js-dropdown-label', [droplabAjax, droplabFilter], {
droplabAjax: {
filterMethod(item, query) { endpoint: 'labels.json',
const { value } = gl.FilteredSearchTokenizer.getLastTokenObject(query); method: 'setData',
const valueWithoutColon = value.slice(1).toLowerCase(); },
const valueWithoutPrefix = valueWithoutColon.slice(1); droplabFilter: {
filterFunction: this.filterWithSymbol.bind(this),
const title = item.title.toLowerCase(); }
const noTitleMatch = title.indexOf(valueWithoutPrefix) === -1 && title.indexOf(valueWithoutColon) === -1; });
item.droplab_hidden = noTitleMatch;
return item;
} }
} }
......
...@@ -3,9 +3,10 @@ ...@@ -3,9 +3,10 @@
((global) => { ((global) => {
class DropdownMilestone extends gl.FilteredSearchDropdown { class DropdownMilestone extends gl.FilteredSearchDropdown {
constructor(dropdown, input) { constructor(droplab, dropdown, input) {
super(dropdown, input); super(droplab, dropdown, input);
this.listId = 'js-dropdown-milestone'; this.listId = 'js-dropdown-milestone';
this.filterSymbol = '%';
} }
itemClicked(e) { itemClicked(e) {
...@@ -21,21 +22,16 @@ ...@@ -21,21 +22,16 @@
} }
renderContent() { renderContent() {
super.renderContent(); // TODO: Pass elements instead of querySelectors
droplab.setData(this.hookId, 'milestones.json'); this.droplab.changeHookList(this.hookId, '#js-dropdown-milestone', [droplabAjax, droplabFilter], {
} droplabAjax: {
endpoint: 'milestones.json',
filterMethod(item, query) { method: 'setData',
const { value } = gl.FilteredSearchTokenizer.getLastTokenObject(query); },
const valueWithoutColon = value.slice(1).toLowerCase(); droplabFilter: {
const valueWithoutPrefix = valueWithoutColon.slice(1); filterFunction: this.filterWithSymbol.bind(this),
}
const title = item.title.toLowerCase(); });
const noTitleMatch = title.indexOf(valueWithoutPrefix) === -1 && title.indexOf(valueWithoutColon) === -1;
item.droplab_hidden = noTitleMatch;
return item;
} }
} }
......
...@@ -3,7 +3,8 @@ ...@@ -3,7 +3,8 @@
const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger'; const DATA_DROPDOWN_TRIGGER = 'data-dropdown-trigger';
class FilteredSearchDropdown { class FilteredSearchDropdown {
constructor(dropdown, input) { constructor(droplab, dropdown, input) {
this.droplab = droplab;
this.hookId = 'filtered-search'; this.hookId = 'filtered-search';
this.input = input; this.input = input;
this.dropdown = dropdown; this.dropdown = dropdown;
...@@ -66,25 +67,11 @@ ...@@ -66,25 +67,11 @@
destroy() { destroy() {
this.input.setAttribute(DATA_DROPDOWN_TRIGGER, ''); this.input.setAttribute(DATA_DROPDOWN_TRIGGER, '');
droplab.setConfig(this.getFilterConfig()); this.droplab.setConfig(this.getFilterConfig());
droplab.setData(this.hookId, []); this.droplab.setData(this.hookId, []);
this.unbindEvents(); this.unbindEvents();
} }
show() {
const currentHook = this.getCurrentHook();
if (currentHook) {
currentHook.list.show();
}
}
hide() {
const currentHook = this.getCurrentHook();
if (currentHook) {
currentHook.list.hide();
}
}
dismissDropdown() { dismissDropdown() {
this.input.focus(); this.input.focus();
// Propogate input change to FilteredSearchManager // Propogate input change to FilteredSearchManager
...@@ -111,30 +98,24 @@ ...@@ -111,30 +98,24 @@
} }
getCurrentHook() { getCurrentHook() {
return droplab.hooks.filter(h => h.id === this.hookId)[0]; return this.droplab.hooks.filter(h => h.id === this.hookId)[0];
} }
renderContent() { renderContent() {
droplab.setConfig(this.getFilterConfig(this.filterKeyword)); // Overriden by dropdown sub class
} }
render(hide) { render(forceRenderContent) {
this.setAsDropdown(); this.setAsDropdown();
const firstTimeInitialized = this.getCurrentHook() === undefined; const firstTimeInitialized = this.getCurrentHook() === undefined;
if (firstTimeInitialized) { if (firstTimeInitialized || forceRenderContent) {
this.renderContent(); this.renderContent();
} else if(this.getCurrentHook().list.list.id !== this.listId) { } else if(this.getCurrentHook().list.list.id !== this.listId) {
droplab.changeHookList(this.hookId, `#${this.listId}`); // this.droplab.changeHookList(this.hookId, `#${this.listId}`);
this.renderContent(); this.renderContent();
} }
if (hide) {
this.hide();
} else {
this.show();
}
} }
resetFilters() { resetFilters() {
...@@ -152,6 +133,29 @@ ...@@ -152,6 +133,29 @@
} }
} }
} }
hide() {
const currentHook = this.getCurrentHook();
if (currentHook) {
currentHook.list.hide();
}
}
filterWithSymbol(item, query) {
const { value } = gl.FilteredSearchTokenizer.getLastTokenObject(query);
const valueWithoutColon = value.slice(1).toLowerCase();
const prefix = valueWithoutColon[0];
const valueWithoutPrefix = valueWithoutColon.slice(1);
const title = item.title.toLowerCase();
// Eg. this.filterSymbol = ~ for labels
const matchWithoutPrefix = prefix === this.filterSymbol && title.indexOf(valueWithoutPrefix) !== -1;
const match = title.indexOf(valueWithoutColon) !== -1;
item.droplab_hidden = !match && !matchWithoutPrefix;
return item;
}
} }
global.FilteredSearchDropdown = FilteredSearchDropdown; global.FilteredSearchDropdown = FilteredSearchDropdown;
......
...@@ -101,11 +101,18 @@ ...@@ -101,11 +101,18 @@
} }
loadDropdown(dropdownName = '', hideDropdown) { loadDropdown(dropdownName = '', hideDropdown) {
let firstLoad = false;
const filteredSearch = document.querySelector('.filtered-search');
if(!this.droplab) {
firstLoad = true;
this.droplab = new DropLab();
}
dropdownName = dropdownName.toLowerCase(); dropdownName = dropdownName.toLowerCase();
const filterIconPadding = 27; const filterIconPadding = 27;
const match = gl.FilteredSearchTokenKeys.get().filter(value => value.key === dropdownName)[0]; const match = gl.FilteredSearchTokenKeys.get().filter(value => value.key === dropdownName)[0];
const filteredSearch = document.querySelector('.filtered-search');
if (!this.font) { if (!this.font) {
this.font = window.getComputedStyle(filteredSearch).font; this.font = window.getComputedStyle(filteredSearch).font;
...@@ -116,34 +123,38 @@ ...@@ -116,34 +123,38 @@
const dynamicDropdownPadding = 12; const dynamicDropdownPadding = 12;
const dropdownOffset = gl.text.getTextWidth(filteredSearch.value, this.font) + filterIconPadding + dynamicDropdownPadding; const dropdownOffset = gl.text.getTextWidth(filteredSearch.value, this.font) + filterIconPadding + dynamicDropdownPadding;
const dropdownAuthorElement = document.querySelector('#js-dropdown-author');
const dropdownAssigneeElement = document.querySelector('#js-dropdown-assignee');
const dropdownMilestoneElement = document.querySelector('#js-dropdown-milestone');
const dropdownLabelElemenet = document.querySelector('#js-dropdown-label');
this.dismissCurrentDropdown(); this.dismissCurrentDropdown();
this.currentDropdown = match.key; this.currentDropdown = match.key;
if (match.key === 'author') { if (match.key === 'author') {
if (!dropdownAuthor) { if (!dropdownAuthor) {
dropdownAuthor = new gl.DropdownAuthor(document.querySelector('#js-dropdown-author'), filteredSearch); dropdownAuthor = new gl.DropdownAuthor(this.droplab, dropdownAuthorElement, filteredSearch);
} }
dropdownAuthor.setOffset(dropdownOffset); dropdownAuthor.setOffset(dropdownOffset);
dropdownAuthor.render(); dropdownAuthor.render();
} else if (match.key === 'assignee') { } else if (match.key === 'assignee') {
if (!dropdownAssignee) { if (!dropdownAssignee) {
dropdownAssignee = new gl.DropdownAssignee(document.querySelector('#js-dropdown-assignee'), filteredSearch); dropdownAssignee = new gl.DropdownAssignee(this.droplab, dropdownAssigneeElement, filteredSearch);
} }
dropdownAssignee.setOffset(dropdownOffset); dropdownAssignee.setOffset(dropdownOffset);
dropdownAssignee.render(); dropdownAssignee.render();
} else if (match.key === 'milestone') { } else if (match.key === 'milestone') {
if (!dropdownMilestone) { if (!dropdownMilestone) {
dropdownMilestone = new gl.DropdownMilestone(document.querySelector('#js-dropdown-milestone'), filteredSearch); dropdownMilestone = new gl.DropdownMilestone(this.droplab, dropdownMilestoneElement, filteredSearch);
} }
dropdownMilestone.setOffset(dropdownOffset); dropdownMilestone.setOffset(dropdownOffset);
dropdownMilestone.render(); dropdownMilestone.render();
} else if (match.key === 'label') { } else if (match.key === 'label') {
if (!dropdownLabel) { if (!dropdownLabel) {
dropdownLabel = new gl.DropdownLabel(document.querySelector('#js-dropdown-label'), filteredSearch); dropdownLabel = new gl.DropdownLabel(this.droplab, dropdownLabelElemenet, filteredSearch);
} }
dropdownLabel.setOffset(dropdownOffset); dropdownLabel.setOffset(dropdownOffset);
...@@ -154,22 +165,29 @@ ...@@ -154,22 +165,29 @@
console.log('🦄 load hint dropdown'); console.log('🦄 load hint dropdown');
const dropdownOffset = gl.text.getTextWidth(filteredSearch.value, this.font) + filterIconPadding; const dropdownOffset = gl.text.getTextWidth(filteredSearch.value, this.font) + filterIconPadding;
console.log(dropdownOffset) const dropdownHintElement = document.querySelector('#js-dropdown-hint');
this.dismissCurrentDropdown(); this.dismissCurrentDropdown();
this.currentDropdown = 'hint'; this.currentDropdown = 'hint';
if (!dropdownHint) { if (!dropdownHint) {
dropdownHint = new gl.DropdownHint(document.querySelector('#js-dropdown-hint'), filteredSearch, this.currentDropdown); dropdownHint = new gl.DropdownHint(this.droplab, dropdownHintElement, filteredSearch);
}
if (firstLoad) {
dropdownHint.configure();
} }
dropdownHint.setOffset(dropdownOffset); dropdownHint.setOffset(dropdownOffset);
dropdownHint.render(hideDropdown); dropdownHint.render(firstLoad);
} }
} }
dismissCurrentDropdown() { dismissCurrentDropdown() {
if (this.currentDropdown === 'hint') { // if (this.currentDropdown === 'hint') {
dropdownHint.destroy(); // dropdownHint.hide();
} // } else if (this.currentDropdown === 'author') {
// // dropdownAuthor.hide();
// }
} }
setDropdown() { setDropdown() {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment