0 Replies Latest reply on Nov 22, 2007 5:19 PM by richajon

    Triggering the suggestionbox using javascript

      Hi

      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?