Triggering the suggestionbox using javascript
richajon Nov 22, 2007 5:19 PMHi
Concerning : http://jira.jboss.com/jira/browse/RF-413
Just like other users on this forum I wanted to add a different way to trigger the suggestion of options to the suggestionbox. In my case, I wanted to give the sgbox the behavior of a windows dropdown like component by adding a image/button next to it that would trigger the ajax call. (the same as the keydown does).
I used Prototype to add an event listener on my image[btn_sugg] and overriden the onKeyPress and updateElement functions in the Richfaces.Suggestion javascript object:
//Inline javascript place after the suggestionbox Event.observe("btn_sugg", "click", doSomething); function doSomething(e) { sugg_box.onKeyPress(e); }
RichFaces.Suggestion.prototype.onKeyPress = function(event) { if (this.isUnloaded()) return; if (!this.initialized) { if (this.options.iframeId) { var iFrame = $(this.options.iframeId); var iTemp = iFrame.cloneNode(true); iFrame.parentNode.removeChild(iFrame); document.body.insertBefore(iTemp, document.body.firstChild); } var temp = this.update.cloneNode(true); this.update.parentNode.removeChild(this.update); this.update = temp; document.body.insertBefore(this.update, document.body.firstChild); this.initialized = true; } this.wasBlur = false; if (this.active) { this.wasScroll = false; switch (event.keyCode) { case Event.KEY_TAB: case Event.KEY_RETURN: if (this.oldValue != this.element.value) { break; //value changed, don't select, propose new choices based on the string } this.selectEntry(event); Event.stop(event); case Event.KEY_ESC: this.hide(); this.active = false; Event.stop(event); if (this.isOpera) { this.element.focus(); } return; case Event.KEY_LEFT: case Event.KEY_RIGHT: return; case Event.KEY_UP: this.keyEvent = true; this.markPrevious(); this.render(); if (navigator.appVersion.indexOf('AppleWebKit') > 0) Event.stop(event); if (this.isOpera) { this.upDown = 1; this.prevOnKeyPress = this.element.onkeypress; this.element.onkeypress = this.onBoxKeyPress.bindAsEventListener(this); } return; case Event.KEY_DOWN: this.keyEvent = true; this.markNext(); this.render(); if (navigator.appVersion.indexOf('AppleWebKit') > 0) Event.stop(event); if (this.isOpera) { this.upDown = 2; this.prevOnKeyPress = this.element.onkeypress; this.element.onkeypress = this.onBoxKeyPress.bindAsEventListener(this); } return; case 33: this.keyEvent = true; this.markPreviousPage(); this.render(); if (navigator.appVersion.indexOf('AppleWebKit') > 0) Event.stop(event); if (this.isOpera) { this.upDown = 3; this.prevOnKeyPress = this.element.onkeypress; this.element.onkeypress = this.onBoxKeyPress.bindAsEventListener(this); } return; case 34: this.keyEvent = true; this.markNextPage(); this.render(); if (navigator.appVersion.indexOf('AppleWebKit') > 0) Event.stop(event); if (this.isOpera) { this.upDown = 4; this.prevOnKeyPress = this.element.onkeypress; this.element.onkeypress = this.onBoxKeyPress.bindAsEventListener(this); } return; } } else if (event.keyCode == Event.KEY_TAB || event.keyCode == Event.KEY_ESC) { return; } this.changed = true; this.hasFocus = true; if (this.observerHandle) { LOG.debug("clear existing observer"); window.clearTimeout(this.observerHandle); } LOG.debug("set timeout for request suggestion"); // Clone event. after call in timeout handdler, original event is unaccesible. var domEvt = {}; try { domEvt.target = event.target; domEvt.srcElement = event.srcElement; domEvt.type = event.type; domEvt.altKey = event.altKey; domEvt.button = event.button; domEvt.clientX = event.clientX; domEvt.clientY = event.clientY; domEvt.ctrlKey = event.ctrlKey; domEvt.keyCode = event.keyCode; domEvt.modifiers = event.modifiers; domEvt.pageX = event.pageX; domEvt.pageY = event.pageY; domEvt.screenX = event.screenX; domEvt.screenY = event.screenY; domEvt.shiftKey = event.shiftKey; domEvt.which = event.which; } catch(e) { LOG.warn("Exception on clone event"); } //EVENT.CLICK on dropdown like button if (event.keyCode == Event.KEY_DOWN || event.keyCode == Event.KEY_RETURN || event.type == "click") { this.observerHandle = window.setTimeout(this.onObserverEvent.bind(this, domEvt), this.options.frequency * 1000); } } RichFaces.Suggestion.prototype.onObserverEvent = function(event) { LOG.debug("Observer event occurs"); this.changed = false; var oldValue = this.element.value; //EVENT.CLICK on dropdown like button if (event.type == "click") { if (!this.active) { this.startIndicator(); this.getUpdatedChoices(event); } else { this.active = false; this.hide(); } return; } if (this.getToken().length >= this.options.minChars) { LOG.debug("Call data for update choices"); this.startIndicator(); this.getUpdatedChoices(event); } else { this.active = false; this.hide(); } this.oldValue = oldValue; this.observerHandle = null; }
The only problem I was facing with this approach was that RichFaces creates an anonymous javascript instance of the Richfaces.Suggestion object. I had to modifiy the suggestion source code and recompile richfaces. Now the suggestionbox place it's javascript instance in a javascript variable name as the UISuggestionBox.getId();
var j_id23= new RichFaces.Suggestion('_viewRoot','form_name','inputj_id130','form_name:suggj_id130',null,{'minChars':'3','param':'inputvalue','width':'200','frequency':1.0,'eventsQueue':'form_name:suggj_id130','entryClass':'richfaces_suggestionEntry','rows':0,'height':'150','popup':'form_name:suggj_id130','tokens':',[','parameters':{'form_name:suggj_id130':'form_name:suggj_id130'},'selectValueClass':'richfaces_suggestionSelectValue','actionUrl':'/moxxi-prototype/views/test/test.seam'});
Then I put the instance in a non name changing variable using an inline javascript tag so my generated event reference works.
var sugg_box = j_id23;
I did all this by wrapping the suggestionbox in a custom component I created using the CDK.... based on the code sample in the cookbook: http://labs.jboss.com/wiki/RichFacesCookBookCreatingSuggestionBoxDynamically
--
I hope this made any sense, I tried to be as clear as possible...
But here is where I wanted to go with this:
-Why is the suggestionbox javascript instance is anonymous?
-Meanwhile a complete js api is created to control the suggestion box, why not put the instance in a named variable? So programmers can access the suggestionbox javascript instance and make calls to it's method to trigger suggestions on different even then onKeyDown in the textbox?
I think it would be usefull to have access to the JS instance of the suggestionbox. Any idea/comments?