diff --git a/hinter.js b/hinter.js index 3afdc69..e43c4c7 100644 --- a/hinter.js +++ b/hinter.js @@ -57,6 +57,7 @@ var SimpleAutocomplete = function(input, dataLoader, multipleDelimiter, onChange this.allowHTML = allowHTML; // Variables + this.closure = []; this.items = []; this.skipHideCounter = 0; this.selectedIndex = -1; @@ -102,16 +103,16 @@ SimpleAutocomplete.prototype.init = function() var self = this; var ie_opera = navigator.userAgent.match('MSIE') || navigator.userAgent.match('Opera'); if (ie_opera) - addListener(e, 'keydown', function(ev) { return self.onKeyPress(ev); }); + this.addRmListener('keydown', function(ev) { return self.onKeyPress(ev); }); else { - addListener(e, 'keydown', function(ev) { return self.onKeyDown(ev); }); - addListener(e, 'keypress', function(ev) { return self.onKeyPress(ev); }); + this.addRmListener('keydown', function(ev) { return self.onKeyDown(ev); }); + this.addRmListener('keypress', function(ev) { return self.onKeyPress(ev); }); } - addListener(e, 'keyup', function(ev) { return self.onKeyUp(ev); }); - addListener(e, 'change', function() { return self.onChange(); }); - addListener(e, 'focus', function() { return self.onInputFocus(); }); - addListener(e, 'blur', function() { return self.onInputBlur(); }); + this.addRmListener('keyup', function(ev) { return self.onKeyUp(ev); }); + this.addRmListener('change', function() { return self.onChange(); }); + this.addRmListener('focus', function() { return self.onInputFocus(); }); + this.addRmListener('blur', function() { return self.onInputBlur(); }); this.onChange(); }; @@ -152,6 +153,37 @@ SimpleAutocomplete.prototype.replaceItems = function(items) } }; +// Add removable listener (remember the function) +SimpleAutocomplete.prototype.addRmListener = function(n, f) +{ + this.closure[n] = f; + addListener(this.input, n, f); +}; + +// Remove instance ("destructor") +SimpleAutocomplete.prototype.remove = function() +{ + if (!this.hintLayer) + return; + this.hintLayer.parentNode.removeChild(this.hintLayer); + for (var i in this.closure) + { + removeListener(this.input, i, this.closure[i]); + } + for (var i = 0; i < SimpleAutocomplete.SimpleAutocompletes.length; i++) + { + if (SimpleAutocomplete.SimpleAutocompletes[i] == this) + { + SimpleAutocomplete.SimpleAutocompletes.splice(i, 1); + break; + } + } + this.closure = {}; + this.input = null; + this.hintLayer = null; + this.items = null; +}; + // Create a drop-down list item, include checkbox if this.multipleDelimiter is true SimpleAutocomplete.prototype.makeItem = function(name, value, checked) { @@ -454,26 +486,21 @@ SimpleAutocomplete.GlobalMouseDown = function(ev) }; // *** UTILITY FUNCTIONS *** -// Remove this section if you already have these functions somewhere else included +// Remove this section if you already have these functions defined somewhere else -// Cross-browser adding of event listeners +// Cross-browser add/remove event listeners var addListener = function() { - if (window.addEventListener) - { - return function(el, type, fn) { el.addEventListener(type, fn, false); }; - } - else if (window.attachEvent) - { - return function(el, type, fn) { - var f = function() { return fn.call(el, window.event); }; - el.attachEvent('on'+type, f); - }; - } - else - { - return function(el, type, fn) { element['on'+type] = fn; } - } + return window.addEventListener + ? function(el, type, fn) { el.addEventListener(type, fn, false); } + : function(el, type, fn) { el.attachEvent('on'+type, fn); }; +}(); + +var removeListener = function() +{ + return window.removeEventListener + ? function(el, type, fn) { el.removeEventListener(type, fn, false); } + : function(el, type, fn) { el.detachEvent('on'+type, fn); }; }(); // Cancel event bubbling and/or default action