Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClement Ho <ClemMakesApps@gmail.com>2016-11-02 23:58:21 +0300
committerClement Ho <ClemMakesApps@gmail.com>2016-11-02 23:58:21 +0300
commit1cb030aa1cead22309cafc518daac49fa8f4f45d (patch)
tree33d5091fbaf6301d536b2f860f0a05db9b4e9b75
parent19e2082fa6b1a483ccf11ce1d6af65b94333e51b (diff)
Add droplab
-rw-r--r--app/assets/javascripts/application.js1
-rw-r--r--app/assets/javascripts/droplab/droplab.js368
-rw-r--r--app/assets/javascripts/droplab/droplab_ajax.js44
-rw-r--r--app/assets/stylesheets/framework/filters.scss5
-rw-r--r--app/views/shared/issuable/_search_bar.html.haml3
5 files changed, 420 insertions, 1 deletions
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 7dd9adac736..5d643d0c156 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -51,6 +51,7 @@
/*= require_directory ./extensions */
/*= require_directory ./lib/utils */
/*= require_directory ./u2f */
+/*= require_directory ./droplab */
/*= require_directory . */
/*= require fuzzaldrin-plus */
diff --git a/app/assets/javascripts/droplab/droplab.js b/app/assets/javascripts/droplab/droplab.js
new file mode 100644
index 00000000000..3640be423d3
--- /dev/null
+++ b/app/assets/javascripts/droplab/droplab.js
@@ -0,0 +1,368 @@
+(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":10}],3:[function(require,module,exports){
+var CustomEvent = require('./custom_event_polyfill');
+var utils = require('./utils');
+
+var DropDown = function(list, trigger) {
+ this.hidden = true;
+ this.list = list;
+ this.trigger = trigger;
+ this.items = [];
+ this.getItems();
+ this.addEvents();
+};
+
+Object.assign(DropDown.prototype, {
+ getItems: function() {
+ this.items = [].slice.call(this.list.querySelectorAll('li'));
+ },
+
+ addEvents: function() {
+ var self = this;
+ // event delegation.
+ this.list.addEventListener('click', function(e) {
+ if(e.target.tagName === 'A') {
+ self.hide();
+ var listEvent = new CustomEvent('click.dl', {
+ detail: {
+ list: self,
+ selected: e.target,
+ data: e.target.dataset,
+ },
+ });
+ self.list.dispatchEvent(listEvent);
+ }
+ });
+ },
+
+ toggle: function() {
+ if(this.hidden) {
+ this.show();
+ } else {
+ this.hide();
+ }
+ },
+
+ addData: function(data) {
+ // empty the list first
+ var sampleItem;
+ var newChildren = [];
+ var toAppend;
+
+ this.items.forEach(function(item) {
+ sampleItem = item;
+ if(item.parentNode && item.parentNode.dataset.hasOwnProperty('dynamic')) {
+ item.parentNode.removeChild(item);
+ }
+
+ });
+
+ this.data = (this.data || []).concat(data);
+
+ newChildren = this.data.map(function(dat){
+ return utils.t(sampleItem.outerHTML, dat);
+ });
+ toAppend = this.list.querySelector('ul[data-dynamic]');
+ if(toAppend) {
+ toAppend.innerHTML = newChildren.join('');
+ } else {
+ this.list.innerHTML = newChildren.join('');
+ }
+ },
+
+ show: function() {
+ this.list.style.display = 'block';
+ this.hidden = false;
+ },
+
+ hide: function() {
+ this.list.style.display = 'none';
+ this.hidden = true;
+ },
+});
+
+module.exports = DropDown;
+
+},{"./custom_event_polyfill":2,"./utils":9}],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.plugins = [];
+ if(typeof hook !== 'undefined'){
+ this.addHook(hook);
+ }
+ this.addEvents();
+ };
+
+ Object.assign(DropLab.prototype, {
+ plugin: function (plugin) {
+ this.plugins.push(plugin)
+ },
+
+ addData: function () {
+ var args = [].slice.apply(arguments);
+ if(this.ready) {
+ this._addData.apply(this, args);
+ } else {
+ this.queuedData = this.queuedData || [];
+ this.queuedData.push(args);
+ }
+ },
+
+ _addData: function(trigger, data) {
+ this.hooks.forEach(function(hook) {
+ if(hook.trigger.dataset.hasOwnProperty('id')) {
+ if(hook.trigger.dataset.id === trigger) {
+ hook.list.addData(data);
+ }
+ }
+ });
+ },
+
+ addEvents: function() {
+ var self = this;
+ window.addEventListener('click', function(e){
+ var thisTag = e.target;
+ if(thisTag.tagName === 'LI' || thisTag.tagName === 'A'){
+ // climb up the tree to find the UL
+ thisTag = utils.closest(thisTag, 'UL');
+ }
+ if(utils.isDropDownParts(thisTag)){ return }
+ if(utils.isDropDownParts(e.target)){ return }
+ self.hooks.forEach(function(hook) {
+ hook.list.hide();
+ });
+ });
+ },
+
+ addHook: function(hook) {
+ if(!(hook instanceof HTMLElement) && typeof hook === 'string'){
+ hook = document.querySelector(hook);
+ }
+ var list = document.querySelector(hook.dataset[utils.toDataCamelCase(DATA_TRIGGER)]);
+ if(hook.tagName === 'A' || hook.tagName === 'button') {
+ this.hooks.push(new HookButton(hook, list));
+ } else if(hook.tagName === 'INPUT') {
+ this.hooks.push(new HookInput(hook, list));
+ }
+ return this;
+ },
+
+ addHooks: function(hooks) {
+ hooks.forEach(this.addHook.bind(this));
+ return this;
+ },
+
+ init: function () {
+ this.plugins.forEach(function(plugin) {
+ plugin(DropLab);
+ })
+ var readyEvent = new CustomEvent('ready.dl', {
+ detail: {
+ dropdown: this,
+ },
+ });
+ window.dispatchEvent(readyEvent);
+ this.ready = true;
+ this.queuedData.forEach(function (args) {
+ this.addData.apply(this, args);
+ }.bind(this));
+ this.queuedData = [];
+ return this;
+ },
+ });
+
+ return DropLab;
+ };
+});
+
+},{"./constants":1,"./custom_event_polyfill":2,"./hook_button":6,"./hook_input":7,"./utils":9,"./window":10}],5:[function(require,module,exports){
+var DropDown = require('./dropdown');
+
+var Hook = function(trigger, list){
+ this.trigger = trigger;
+ this.list = new DropDown(list);
+ this.type = 'Hook';
+ this.event = 'click';
+};
+
+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) {
+ Hook.call(this, trigger, list);
+ this.type = 'button';
+ this.event = 'click';
+ this.addEvents();
+};
+
+HookButton.prototype = Object.create(Hook.prototype);
+
+Object.assign(HookButton.prototype, {
+ addEvents: function(){
+ var self = this;
+ this.trigger.addEventListener('click', function(e){
+ var buttonEvent = new CustomEvent('click.dl', {
+ detail: {
+ hook: self,
+ },
+ });
+ self.list.show();
+ e.target.dispatchEvent(buttonEvent);
+ });
+ },
+
+ 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) {
+ Hook.call(this, trigger, list);
+ this.type = 'input';
+ this.event = 'input';
+ this.addEvents();
+};
+
+Object.assign(HookInput.prototype, {
+ addEvents: function(){
+ var self = this;
+ this.trigger.addEventListener('input', function(e){
+ var inputEvent = new CustomEvent('input.dl', {
+ detail: {
+ hook: self,
+ text: e.target.value,
+ },
+ });
+ e.target.dispatchEvent(inputEvent);
+ self.list.show();
+ });
+ },
+});
+
+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 setup = function() {
+ var 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();
+
+},{"./constants":1,"./droplab":4,"./window":10}],9:[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.tagName !== stopTag && thisTag.tagName !== 'HTML'){
+ thisTag = thisTag.parentNode;
+ }
+ return thisTag;
+};
+
+var isDropDownParts = function(target) {
+ if(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}],10:[function(require,module,exports){
+module.exports = function(callback) {
+ return (function() {
+ callback(this);
+ }).call(null);
+};
+
+},{}]},{},[8])(8)
+}); \ No newline at end of file
diff --git a/app/assets/javascripts/droplab/droplab_ajax.js b/app/assets/javascripts/droplab/droplab_ajax.js
new file mode 100644
index 00000000000..b2eba5d5a78
--- /dev/null
+++ b/app/assets/javascripts/droplab/droplab_ajax.js
@@ -0,0 +1,44 @@
+(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 */
+droplab.plugin(function init(DropLab) {
+ var _addData = DropLab.prototype.addData;
+
+ var _loadUrlData = function(url) {
+ 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);
+ return resolve(data);
+ } else {
+ return reject([xhr.responseText, xhr.status]);
+ }
+ }
+ };
+ xhr.send();
+ });
+ };
+
+ Object.assign(DropLab.prototype, {
+ addData: function(trigger, data) {
+ var _this = this;
+ if('string' === typeof data) {
+ _loadUrlData(data).then(function(d) {
+ _addData.call(_this, trigger, 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
+ })
+ } else {
+ _addData.apply(this, arguments);
+ }
+ },
+ });
+});
+
+},{}]},{},[1])(1)
+}); \ No newline at end of file
diff --git a/app/assets/stylesheets/framework/filters.scss b/app/assets/stylesheets/framework/filters.scss
index 569ae7b850c..3efe95f3012 100644
--- a/app/assets/stylesheets/framework/filters.scss
+++ b/app/assets/stylesheets/framework/filters.scss
@@ -81,3 +81,8 @@
@extend .form-control:focus
}
}
+
+.droplab-menu {
+ position: relative;
+ top: 0;
+} \ No newline at end of file
diff --git a/app/views/shared/issuable/_search_bar.html.haml b/app/views/shared/issuable/_search_bar.html.haml
index e9eaefbe3b5..b6fe4754ec7 100644
--- a/app/views/shared/issuable/_search_bar.html.haml
+++ b/app/views/shared/issuable/_search_bar.html.haml
@@ -15,7 +15,8 @@
= icon('filter')
%ul.fragment-list
%li.fragment-search
- %input.filtered-search.transparent{ placeholder: 'Search or filter results...' }
+ %input.filtered-search.transparent{ placeholder: 'Search or filter results...', 'data-dropdown-trigger' => '#filter-dropdown' }
+ %ul.dropdown-menu.droplab-menu#filter-dropdown{ 'data-dropdown' => true}
.pull-right
- if boards_page
#js-boards-seach.issue-boards-search