зеркало из https://github.com/mozilla/FlightDeck.git
converted Autocomplete to Shipyard
This commit is contained in:
Родитель
3c88665253
Коммит
d62aa98a74
|
@ -0,0 +1,247 @@
|
|||
var Class = require('shipyard/class/Class'),
|
||||
Options = require('shipyard/class/Options'),
|
||||
Events = require('shipyard/class/Events'),
|
||||
Request = require('shipyard/http/Request'),
|
||||
dom = require('shipyard/dom'),
|
||||
string = require('shipyard/utils/string');
|
||||
|
||||
var CONTROL_KEYS = {
|
||||
esc: 1,
|
||||
enter: 1,
|
||||
up: 1,
|
||||
down: 1,
|
||||
shift: 1
|
||||
};
|
||||
|
||||
module.exports = new Class({
|
||||
|
||||
Implements: [Events, Options],
|
||||
|
||||
options: {
|
||||
valueField: null,
|
||||
valueFilter: null,
|
||||
filter: null,
|
||||
minChars: 2,
|
||||
limit: 20,
|
||||
hoverClass: 'fd-hover',
|
||||
loadingClass: 'fd-loading'
|
||||
},
|
||||
|
||||
_cache: {},
|
||||
|
||||
initialize: function(input, url, options) {
|
||||
this.input = dom.$(input);
|
||||
this.url = url;
|
||||
this.setOptions(options);
|
||||
|
||||
this.element = new dom.Element('div', {
|
||||
'class': 'fd-autocomplete',
|
||||
'id': string.uniqueID()
|
||||
});
|
||||
dom.document.body.appendChild(this.element);
|
||||
|
||||
this.valueField = dom.$(this.getOption('valueField')) || this.input;
|
||||
|
||||
this._addInputEvents();
|
||||
this._addListEvents();
|
||||
this._createEmptyWarning();
|
||||
this.positionNextTo();
|
||||
},
|
||||
|
||||
_addInputEvents: function() {
|
||||
var ac = this;
|
||||
this.input.addListener('keyup', function(e) {
|
||||
if (e.key in CONTROL_KEYS) {
|
||||
return;
|
||||
}
|
||||
ac._setupList();
|
||||
});
|
||||
this.input.addListener('blur', function(e) {
|
||||
ac.hide();
|
||||
});
|
||||
this.input.addListener('keydown', function(e) {
|
||||
var nextItem;
|
||||
if (ac._isShowing) {
|
||||
switch (e.key) {
|
||||
case 'enter':
|
||||
//select currently focusedItem
|
||||
e.stop();
|
||||
ac._selectFocusedItem();
|
||||
break;
|
||||
case 'esc':
|
||||
//hide list
|
||||
e.stop();
|
||||
ac.hide();
|
||||
break;
|
||||
case 'up':
|
||||
//focus previous item
|
||||
e.stop();
|
||||
if (ac._focusedItem) {
|
||||
nextItem = ac._focusedItem.getPrevious('li');
|
||||
}
|
||||
if (!nextItem) {
|
||||
nextItem = ac.element.getElement('ul').getLast('li');
|
||||
}
|
||||
ac._focusItem(nextItem);
|
||||
break;
|
||||
case 'down':
|
||||
//focus next item
|
||||
e.stop();
|
||||
if (ac._focusedItem) {
|
||||
nextItem = ac._focusedItem.getNext('li');
|
||||
}
|
||||
if (!nextItem) {
|
||||
nextItem = ac.element.getElement('ul').getFirst('li');
|
||||
}
|
||||
ac._focusItem(nextItem);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
_addListEvents: function() {
|
||||
var ac = this;
|
||||
this.element.delegate('li', 'mouseover', function(e, li) {
|
||||
ac._focusItem(li);
|
||||
});
|
||||
this.element.delegate('li', 'click', function(e, li) {
|
||||
ac._selectFocusedItem();
|
||||
});
|
||||
},
|
||||
|
||||
_createEmptyWarning: function() {
|
||||
var warning = this._warning = new dom.Element('div', {
|
||||
'class': 'autocomplete roar tip warning',
|
||||
'html': '<div class="roar-bg"></div><h3>No libraries found.</h3><p>Check your spelling?</p>'
|
||||
}).inject(this.input, 'after');
|
||||
|
||||
var pos = this.input.getPosition(),
|
||||
size = this.input.getSize();
|
||||
|
||||
warning.setStyles({
|
||||
top: 50,
|
||||
left: size.x + 55,
|
||||
position: 'absolute'
|
||||
});
|
||||
|
||||
warning.setStyle('visibility', 'hidden');
|
||||
},
|
||||
|
||||
_focusItem: function(item) {
|
||||
if (item === this._focusedItem) {
|
||||
return;
|
||||
}
|
||||
var hoverClass = this.getOption('hoverClass');
|
||||
if (this._focusedItem) {
|
||||
this._focusedItem.removeClass(hoverClass);
|
||||
}
|
||||
item.addClass(hoverClass);
|
||||
this._focusedItem = item;
|
||||
this.emit('focusItem', item);
|
||||
},
|
||||
|
||||
_selectFocusedItem: function() {
|
||||
if (this._focusedItem) {
|
||||
var index = this._focusedItem.get('data-index');
|
||||
var data = this._cache[this._text];
|
||||
var valueFilter = this.getOption('valueFilter');
|
||||
this.input.set('value', data[index].full_name);
|
||||
this.valueField.set('value', valueFilter(data[index]));
|
||||
|
||||
this.emit('select');
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
_setupList: function _setupList() {
|
||||
this._text = this.input.get('value').trim();
|
||||
if (this._cache[this._text]) {
|
||||
this._renderList();
|
||||
} else {
|
||||
this._fetchList();
|
||||
}
|
||||
},
|
||||
|
||||
_fetchList: function _fetchList() {
|
||||
var ac = this,
|
||||
text = this._text,
|
||||
loadingClass = this.getOption('loadingClass');
|
||||
this.emit('request', text);
|
||||
this._warning.setStyle('visibility', 'hidden');
|
||||
this.input.addClass(loadingClass);
|
||||
return new Request({
|
||||
url: this.url,
|
||||
method: 'get',
|
||||
data: {
|
||||
q: text,
|
||||
limit: this.getOption('limit')
|
||||
},
|
||||
onSuccess: function(response) {
|
||||
response = JSON.parse(response);
|
||||
ac._cache[text] = response;
|
||||
ac._renderList();
|
||||
},
|
||||
onComplete: function() {
|
||||
ac.input.removeClass(loadingClass);
|
||||
}
|
||||
}).send();
|
||||
},
|
||||
|
||||
_renderList: function() {
|
||||
var data = this._cache[this._text];
|
||||
this._focusedItem = null;
|
||||
|
||||
if (data && data.length) {
|
||||
var ul = new dom.Element('ul');
|
||||
data.forEach(function(item, i) {
|
||||
var li = new dom.Element('li');
|
||||
li.set('data-index', i);
|
||||
li.set('html', item.html);
|
||||
ul.appendChild(li);
|
||||
});
|
||||
this.element.empty().appendChild(ul);
|
||||
this._warning.setStyle('visibility', 'hidden');
|
||||
this.emit('render');
|
||||
this.show();
|
||||
} else {
|
||||
this.emit('empty');
|
||||
this._warning.setStyle('visibility', 'visible');
|
||||
this.hide();
|
||||
}
|
||||
},
|
||||
|
||||
show: function() {
|
||||
this.element.setStyle('visibility', 'visible');
|
||||
this._isShowing = true;
|
||||
this.emit('show');
|
||||
},
|
||||
|
||||
hide: function hide() {
|
||||
this.element.setStyle('visibility', 'hidden');
|
||||
this._isShowing = false;
|
||||
this.emit('hide');
|
||||
},
|
||||
|
||||
destroy: function() {
|
||||
this.hide();
|
||||
this.element.destroy();
|
||||
this._warning.destroy();
|
||||
delete this.element;
|
||||
},
|
||||
|
||||
positionNextTo: function(target) {
|
||||
target = dom.$(target || this.input);
|
||||
var pos = target.getPosition();
|
||||
this.element.setStyles({
|
||||
top: pos.y + target.getHeight(),
|
||||
left: pos.x,
|
||||
width: target.getWidth()
|
||||
});
|
||||
},
|
||||
|
||||
toElement: function() {
|
||||
return this.element;
|
||||
}
|
||||
|
||||
});
|
|
@ -11,7 +11,7 @@ license: MIT-style license
|
|||
...
|
||||
*/
|
||||
|
||||
.ma-container {
|
||||
.fd-autocomplete {
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
top: 31px;
|
||||
|
@ -29,13 +29,13 @@ license: MIT-style license
|
|||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.ma-container ul {
|
||||
.fd-autocomplete ul {
|
||||
list-style: none;
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.ma-container li {
|
||||
.fd-autocomplete li {
|
||||
background: transparent;
|
||||
margin: 0;
|
||||
display: block;
|
||||
|
@ -46,24 +46,24 @@ license: MIT-style license
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.ma-container .ma-hover {
|
||||
.fd-autocomplete .fd-hover {
|
||||
background: -moz-linear-gradient(270deg, #5AA2F3, #3E81D2);
|
||||
color: #fff;
|
||||
text-shadow: 0 1px 0 #011E4F;
|
||||
}
|
||||
|
||||
.ma-container .ma-odd {
|
||||
.fd-autocomplete .fd-odd {
|
||||
}
|
||||
|
||||
.ma-container .ma-even {
|
||||
.fd-autocomplete .fd-even {
|
||||
}
|
||||
.ma-loading {
|
||||
.fd-loading {
|
||||
background-image:url('../img/spinner-16.gif');
|
||||
background-repeat:no-repeat;
|
||||
background-position:98% center;
|
||||
}
|
||||
|
||||
.ma-selected {
|
||||
.fd-selected {
|
||||
}
|
||||
|
||||
.autocomplete.tip.roar {
|
||||
|
|
|
@ -98,15 +98,15 @@ body
|
|||
}
|
||||
|
||||
|
||||
.ma-container strong {
|
||||
.fd-autocomplete strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
.ma-container .author {
|
||||
.fd-autocomplete .author {
|
||||
display: block;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.ma-container .description {
|
||||
.fd-autocomplete .description {
|
||||
display: block;
|
||||
font-size: 0.9em;
|
||||
font-style: italic;
|
||||
|
|
|
@ -13,6 +13,7 @@ var Class = require('shipyard/class/Class'),
|
|||
Package = require('../models/Package'),
|
||||
FileTree = require('./FileTree'),
|
||||
filename = require('../utils/filename'),
|
||||
Autocomplete = require('flightdeck/Autocomplete'),
|
||||
URI = require('../utils/URI');
|
||||
|
||||
//TODO: Bad practice.
|
||||
|
@ -686,12 +687,18 @@ var Sidebar = module.exports = new Class({
|
|||
|
||||
//setup Library autocomplete
|
||||
// autocomplete
|
||||
var ac = new FlightDeck.Autocomplete({
|
||||
'url': settings.library_autocomplete_url
|
||||
});
|
||||
dom.$(modal).retrieve('dragger').addEvent('drag', function(el, evt) {
|
||||
var ac = new Autocomplete('new_library', settings.library_autocomplete_url, {
|
||||
valueField: 'library_id_number',
|
||||
valueFilter: function(data) {
|
||||
return data.id_number;
|
||||
}
|
||||
});
|
||||
modal.addListener('drag', function(el, evt) {
|
||||
ac.positionNextTo();
|
||||
});
|
||||
modal.addListener('destroy', function() {
|
||||
ac.destroy();
|
||||
});
|
||||
},
|
||||
|
||||
setPluginUpdate: function(library, latest_revision) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче