Added the autocomplete Inspector editor. Minor fixes in the Inspector memory management. Added destroy() method to the existing autocomplete control.

This commit is contained in:
alekseybobkov 2015-10-05 20:56:35 -07:00
parent c47f69a012
commit 889a25f1c6
6 changed files with 199 additions and 21 deletions

View File

@ -1258,8 +1258,9 @@ this.shown=false
this.listen()}
Autocomplete.prototype={constructor:Autocomplete,select:function(){var val=this.$menu.find('.active').attr('data-value')
this.$element.val(this.updater(val)).change()
return this.hide()},updater:function(item){return item},show:function(){var pos=$.extend({},this.$element.position(),{height:this.$element[0].offsetHeight})
this.$menu.insertAfter(this.$element).css({top:pos.top+pos.height,left:pos.left}).show()
return this.hide()},updater:function(item){return item},show:function(){var pos=$.extend({},this.$element.position(),{height:this.$element[0].offsetHeight}),cssOptions={top:pos.top+pos.height,left:pos.left}
if(this.options.matchWidth){cssOptions.width=this.$element[0].offsetWidth}
this.$menu.insertAfter(this.$element).css(cssOptions).show()
this.shown=true
return this},hide:function(){this.$menu.hide()
this.shown=false
@ -1293,9 +1294,9 @@ return this},next:function(event){var active=this.$menu.find('.active').removeCl
if(!next.length){next=$(this.$menu.find('li')[0])}
next.addClass('active')},prev:function(event){var active=this.$menu.find('.active').removeClass('active'),prev=active.prev()
if(!prev.length){prev=this.$menu.find('li').last()}
prev.addClass('active')},listen:function(){this.$element.on('focus',$.proxy(this.focus,this)).on('blur',$.proxy(this.blur,this)).on('keypress',$.proxy(this.keypress,this)).on('keyup',$.proxy(this.keyup,this))
if(this.eventSupported('keydown')){this.$element.on('keydown',$.proxy(this.keydown,this))}
this.$menu.on('click',$.proxy(this.click,this)).on('mouseenter','li',$.proxy(this.mouseenter,this)).on('mouseleave','li',$.proxy(this.mouseleave,this))},eventSupported:function(eventName){var isSupported=eventName in this.$element
prev.addClass('active')},listen:function(){this.$element.on('focus.autocomplete',$.proxy(this.focus,this)).on('blur.autocomplete',$.proxy(this.blur,this)).on('keypress.autocomplete',$.proxy(this.keypress,this)).on('keyup.autocomplete',$.proxy(this.keyup,this))
if(this.eventSupported('keydown')){this.$element.on('keydown.autocomplete',$.proxy(this.keydown,this))}
this.$menu.on('click.autocomplete',$.proxy(this.click,this)).on('mouseenter.autocomplete','li',$.proxy(this.mouseenter,this)).on('mouseleave.autocomplete','li',$.proxy(this.mouseleave,this))},eventSupported:function(eventName){var isSupported=eventName in this.$element
if(!isSupported){this.$element.setAttribute(eventName,'return;')
isSupported=typeof this.$element[eventName]==='function'}
return isSupported},move:function(e){if(!this.shown)return
@ -1325,7 +1326,13 @@ this.select()
this.$element.focus()},mouseenter:function(e){this.mousedover=true
this.$menu.find('.active').removeClass('active')
$(e.currentTarget).addClass('active')},mouseleave:function(e){this.mousedover=false
if(!this.focused&&this.shown)this.hide()}}
if(!this.focused&&this.shown)this.hide()},destroy:function(){this.hide()
this.$element.removeData('autocomplete')
this.$menu.remove()
this.$element.off('.autocomplete')
this.$menu.off('.autocomplete')
this.$element=null
this.$menu=null}}
var old=$.fn.autocomplete
$.fn.autocomplete=function(option){return this.each(function(){var $this=$(this),data=$this.data('autocomplete'),options=typeof option=='object'&&option
if(!data)$this.data('autocomplete',(data=new Autocomplete(this,options)))

View File

@ -53,14 +53,19 @@
show: function () {
var pos = $.extend({}, this.$element.position(), {
height: this.$element[0].offsetHeight
})
}),
cssOptions = {
top: pos.top + pos.height
, left: pos.left
}
if (this.options.matchWidth) {
cssOptions.width = this.$element[0].offsetWidth
}
this.$menu
.insertAfter(this.$element)
.css({
top: pos.top + pos.height
, left: pos.left
})
.css(cssOptions)
.show()
this.shown = true
@ -194,19 +199,19 @@
listen: function () {
this.$element
.on('focus', $.proxy(this.focus, this))
.on('blur', $.proxy(this.blur, this))
.on('keypress', $.proxy(this.keypress, this))
.on('keyup', $.proxy(this.keyup, this))
.on('focus.autocomplete', $.proxy(this.focus, this))
.on('blur.autocomplete', $.proxy(this.blur, this))
.on('keypress.autocomplete', $.proxy(this.keypress, this))
.on('keyup.autocomplete', $.proxy(this.keyup, this))
if (this.eventSupported('keydown')) {
this.$element.on('keydown', $.proxy(this.keydown, this))
this.$element.on('keydown.autocomplete', $.proxy(this.keydown, this))
}
this.$menu
.on('click', $.proxy(this.click, this))
.on('mouseenter', 'li', $.proxy(this.mouseenter, this))
.on('mouseleave', 'li', $.proxy(this.mouseleave, this))
.on('click.autocomplete', $.proxy(this.click, this))
.on('mouseenter.autocomplete', 'li', $.proxy(this.mouseenter, this))
.on('mouseleave.autocomplete', 'li', $.proxy(this.mouseleave, this))
},
eventSupported: function(eventName) {
@ -305,8 +310,20 @@
mouseleave: function (e) {
this.mousedover = false
if (!this.focused && this.shown) this.hide()
}
},
destroy: function() {
this.hide()
this.$element.removeData('autocomplete')
this.$menu.remove()
this.$element.off('.autocomplete')
this.$menu.off('.autocomplete')
this.$element = null
this.$menu = null
}
}

View File

@ -0,0 +1,146 @@
/*
* Inspector autocomplete editor class.
*
* Depends on october.autocomplete.js
*/
+function ($) { "use strict";
var Base = $.oc.inspector.propertyEditors.string,
BaseProto = Base.prototype
var AutocompleteEditor = function(inspector, propertyDefinition, containerCell, group) {
Base.call(this, inspector, propertyDefinition, containerCell, group)
}
AutocompleteEditor.prototype = Object.create(BaseProto)
AutocompleteEditor.prototype.constructor = Base
AutocompleteEditor.prototype.dispose = function() {
this.removeAutocomplete()
BaseProto.dispose.call(this)
}
AutocompleteEditor.prototype.build = function() {
var container = document.createElement('div'),
editor = document.createElement('input'),
placeholder = this.propertyDefinition.placeholder !== undefined ? this.propertyDefinition.placeholder : '',
value = this.inspector.getPropertyValue(this.propertyDefinition.property)
editor.setAttribute('type', 'text')
editor.setAttribute('class', 'string-editor')
editor.setAttribute('placeholder', placeholder)
container.setAttribute('class', 'autocomplete-container')
if (value === undefined) {
value = this.propertyDefinition.default
}
if (value === undefined) {
value = ''
}
editor.value = value
$.oc.foundation.element.addClass(this.containerCell, 'text autocomplete')
container.appendChild(editor)
this.containerCell.appendChild(container)
if (this.propertyDefinition.items !== undefined) {
this.buildAutoComplete(this.propertyDefinition.items)
}
else {
this.loadDynamicItems()
}
}
AutocompleteEditor.prototype.buildAutoComplete = function(items) {
var input = this.getInput()
if (items === undefined) {
items = []
}
$(input).autocomplete({
source: this.prepareItems(items),
matchWidth: true
})
}
AutocompleteEditor.prototype.removeAutocomplete = function() {
var input = this.getInput()
$(input).autocomplete('destroy')
}
AutocompleteEditor.prototype.prepareItems = function(items) {
var result = {}
if ($.isArray(items)) {
for (var i = 0, len = items.length; i < len; i++) {
result[items[i]] = items[i]
}
}
else {
result = items
}
return result
}
AutocompleteEditor.prototype.supportsExternalParameterEditor = function() {
return false
}
AutocompleteEditor.prototype.getContainer = function() {
return this.getInput().parentNode
}
//
// Dynamic items
//
AutocompleteEditor.prototype.showLoadingIndicator = function() {
$(this.getContainer()).loadIndicator()
}
AutocompleteEditor.prototype.hideLoadingIndicator = function() {
var $container = $(this.getContainer())
$container.loadIndicator('hide')
$container.loadIndicator('destroy')
$container.removeClass('loading-indicator-container')
}
AutocompleteEditor.prototype.loadDynamicItems = function() {
var container = this.getContainer(),
data = this.inspector.getValues(),
$form = $(container).closest('form')
$.oc.foundation.element.addClass(container, 'loading-indicator-container size-small')
this.showLoadingIndicator()
$form.request('onInspectableGetOptions', {
data: data,
})
.done(this.proxy(this.itemsRequestDone))
.always(this.proxy(this.hideLoadingIndicator))
}
AutocompleteEditor.prototype.itemsRequestDone = function(data, currentValue, initialization) {
var loadedItems = {}
if (data.options) {
for (var i = data.options.length-1; i >= 0; i--) {
loadedItems[data.options[i].value] = data.options[i].title
}
}
this.buildAutoComplete(loadedItems)
}
$.oc.inspector.propertyEditors.autocomplete = AutocompleteEditor
}(window.jQuery);

View File

@ -293,6 +293,7 @@
DropdownEditor.prototype.hideLoadingIndicator = function() {
if (!Modernizr.touch) {
this.indicatorContainer.loadIndicator('hide')
this.indicatorContainer.loadIndicator('destroy')
}
}

View File

@ -145,7 +145,10 @@
}
SetEditor.prototype.hideLoadingIndicator = function() {
$(this.getLink()).loadIndicator('hide')
var $link = $(this.getLink())
$link.loadIndicator('hide')
$link.loadIndicator('destroy')
}
SetEditor.prototype.loadDynamicItems = function() {

View File

@ -80,5 +80,9 @@
this.inspector.setPropertyValue(this.propertyDefinition.property, value)
}
StringEditor.prototype.onExternalPropertyEditorHidden = function() {
this.focus()
}
$.oc.inspector.propertyEditors.string = StringEditor
}(window.jQuery);