Click Event on input field

Topics related to using ToolBook for building web apps.

Click Event on input field

Postby Andy » Mon Jun 10, 2019 9:45 am

I have an existing book that contains input fields with a Click event defined. These fire the click event when the field is selected and the user can then enter text as usual. However, when published using PowerPac the click event fires but the field does not get focus for editing. Furthermore, when authoring using ToolBook with PowerPac the Click event is not available even though the activated property is false.

Should this be expected to work? It seems the most direct way to send a User event that tells which field is being used.

Thanks, Andy
Andy
 
Posts: 47
Joined: Tue Sep 09, 2014 3:40 pm

Re: Click Event on input field

Postby Clifton » Mon Jun 10, 2019 11:21 am

How input fields work in a published-to-web book:
  • If activated = true, then fields are converted to <span> elements in the published book and can be set up to accept click events.
  • If activated = false, then fields are converted to <input> or <textarea> elements in the published book and you will not be able to set up a click event on them.
In your project, if are simply trying to ensure which field has focus after a page is loaded, then use this action on the field you want to have the focus:
on load page
pgTBObjSet( name of self, "focus", true, 150); discard return value
 

If instead you need to know which field your user is inputting text, then use this action on each field:
on key up
set curField to name of self
 

You may wish to explore the PowerPac function validateField() as it is designed to monitor/modify the input in editable text fields.

If you really need a click event to fire on an input field, you would probably need to leverage the XML capabilities of the PowerPac as it can do just about anything with your exported content. Here is an XML file which may behave a little like you want. It puts a prompt text in each field on load page and when the user click on a field, it checks whether the prompt text is present and clears it, then ensures the focus is set to the end of the current string of text in the field, if any.
RECOMMENDATION: I would use a focus event instead as that is what the event is designed for. You can see that I've used a focus event on "Field2".
    <?xml version="1.0" encoding="utf-8"?>
    <page>
    <config delay="">
    <!--Make sure no field has focus initially-->
    <pgTBObjSet>
    { tbName : "Field1", myProp : "focus", myValue : false }
    </pgTBObjSet>
    <pgTBObjSet>
    { tbName : "Field2", myProp : "focus", myValue : false }
    </pgTBObjSet>
    </config>

    <!--Object name tags follow initial configuration tags.-->
    <Field1>
    <!--Prompt text to put into the object-->
    <text>
    <![CDATA[
    (Enter your text here.)
    ]]>
    </text>

    <function name="myClick" event="click" params="e">
    <![CDATA[
    /* CLIFTON: This is a click event on an editable text field.
    Clear prompt text and keep focus.
    ***/
    var myTxt = tbfunction_pgTBObjGet( this.name, "text" );
    if ( myTxt == "(Enter your text here.)" ) {
    tbfunction_pgTBObjSet( this.name, "text", "");
    }
    tbfunction_caretPosition( this.name, "end" );
    ]]>
    </function>
    </Field1>

    <Field2>
    <!--Prompt text to put into the object-->
    <text>
    <![CDATA[
    (Enter your text here.)
    ]]>
    </text>

    <function name="myFocus" event="focus" params="e">
    <![CDATA[
    /* CLIFTON: This is a FOCUS event on an editable text field.
    Clear prompt text and keep focus.
    ***/
    var myTxt = tbfunction_pgTBObjGet( this.name, "text" );
    if ( myTxt == "(Enter your text here.)" ) {
    tbfunction_pgTBObjSet( this.name, "text", "");
    }
    tbfunction_caretPosition( this.name, "end" );
    ]]>
    </function>
    </Field2>
    </page>

    The above XML file produces the following interactive result:

     
Attachments
inputField_clickable.zip
ToolBook v11.5 example of above
(121.85 KiB) Downloaded 201 times
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: Click Event on input field

Postby Andy » Mon Jun 10, 2019 12:34 pm

Hi Clifton,
It looks like the existing book that works is generating a form:
<form id="TextEntry_p21o20_form" onsubmit="return TBK._tHfocus(p21.o20,false);">
<textarea wrap="virtual" id="TextEntry_p21o20" href="javascript:void;" tabindex="16397" onfocus="if(TBK)TBK._tHfocus(p21.o20,true);" onblur="if(TBK)TBK._tHfocus(p21.o20,false);" style="background-color:#ffffff;border:0px #000000 none;height:1px;width:601px;visibility:inherit;z-index:16397;cursor:pointer;color:#000000;font-family:'Courier New';font-size:24px;font-style:normal;position:absolute;left:200px;top:100px;padding:0px 5px 0px 5px;overflow:hidden;margin:0px;"></textarea>
</form>

Since the click does fire the event I was hoping that there was a way to just forward that click to the usual handler, but maybe that's not possible. I could send you an example if that would help.

The scenario is that the user sees multiple input fields that represent an outline, like when writing an essay. Any field can accept input, and the user can select different fields to type into as part of the same interaction. If it is the "current" field then it can also be manipulated via additional buttons on the page, for instance to indent it and its sub-entries. So what I need to know is which is the current field.

If there were a way to detect focus of these fields I think that would work. Another way might be if the click is forwarded to the page and there is a way to identify the target the the user clicked on.
Andy
 
Posts: 47
Joined: Tue Sep 09, 2014 3:40 pm

Re: Click Event on input field

Postby Clifton » Mon Jun 10, 2019 1:05 pm

Pretty much most if not all of these options were presented in my earlier post. Just use the key up handler to determine the current target.
Otherwise, ToolBook has no way of making an action on focus. For that you would need to use the XML example I provided earlier.

If you can't get your book to work like you want it to, I would be glad to take a look.
 
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: Click Event on input field

Postby Andy » Wed Jun 12, 2019 2:16 pm

So if I understand the documentation, the following should send the user event I need.
Do I need to define myHandlerObject in the xml even though I'm handling the user event with regular actions?
Also, would there be a way to define the function "myFocus" once and reference it in each of my fields?
Thanks!
<Field2>
<function name="myFocus" event="focus" params="e">
<![CDATA[
/* CLIFTON: This is a click event on an editable text field.
***/
tbfunction_caretPosition( this.name, "end" );
<myHandlerObject>
<pgTBObjSet>
{ myProperty : "user", myValue : this.name }
</pgTBObjSet>
</myHandlerObject>
]]>
</function>
</Field2>
Andy
 
Posts: 47
Joined: Tue Sep 09, 2014 3:40 pm

Re: Click Event on input field

Postby Clifton » Wed Jun 12, 2019 3:59 pm

You can send a user event from XML to the actions you have already created using the Actions Editor.
However, this code in your post may not be doing what you want:
<myHandlerObject>
<pgTBObjSet>
{ myProperty : "user", myValue : this.name }
</pgTBObjSet>
</myHandlerObject>

What you are saying by the above is that you want the XML engine to send a user event to an object named "myHandlerObject" immediately upon loading the XML file (which is essentially on load page). Somehow I don't think that is your intention, but if it is then that is exactly what is happening. The user event will be sent to "myHandlerObject" and any actions defined for the user event on that object will execute.

Your other question is:
Also, would there be a way to define the function "myFocus" once and reference it in each of my fields?
Answer: YES!
    What you need to do is define the common function(s) somewhere in your object hierarchy and send the event data to it. I usually recommend defining a <make> element at level 0 (outside the ToolBook iframe) and put your common functions there. These will not be destroyed on page navigation and the object will work like sharedActions in ToolBook
    Here is how that could be set up to work:
    <make id="sharedActions" type="div" level="0" dims="-50,-50,20,20" class="" refObj="" autoAlign="" replace="">
    <style>
    { "display" : "none" }
    </style>

    <function name="myFieldHandler" event="" params="tbName">
    <![CDATA[
    /* CLIFTON: Receives event information from the fields which receive a click.
    ***/
    alert( "You clicked field: " + tbName );
    tbfunction_caretPosition( tbName, "end" );
    ]]>
    </function>
    </make>

    <Field2>
    <function name="myFocus" event="focus" params="e">
    <![CDATA[
    /* CLIFTON: This is a click event on an editable text field.
    Pass the event target name to the common handler
    ***/
    tbfunction_pgTBObjSet( "sharedActions", "myFieldHandler", [ e.target.name ] );
    ]]>
    </function>
    </Field2>

    NOTE: You will still have to define the focus event on each field. However, the behavior will all be on the "sharedActions" object.
I've uploaded an updated example on one of my previous posts to reflect this example.
 
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: Click Event on input field

Postby Andy » Thu Jun 13, 2019 8:24 am

Thanks for the explanation of how to share the function.
I guess I don't understand how to generate a user event when the field receives focus. It sounds like putting it within the function definition after the call to caretPosition won't accomplish that. Is there another way?
All I really need to do when the field receives focus is to set a global variable to the focused field name, if that is easier.
Thanks again!
Andy
 
Posts: 47
Joined: Tue Sep 09, 2014 3:40 pm

Re: Click Event on input field

Postby Clifton » Thu Jun 13, 2019 9:16 am

It gets easier than you think!
To send user event when field gets the focus, and/or to set a global variable with field name:
<make id="sharedActions" type="div" level="0" dims="-50,-50,20,20" class="" refObj="" autoAlign="" replace="">
<style>
{ "display" : "none" }
</style>

<function name="myFieldHandler" event="" params="tbName">
<![CDATA[
/* CLIFTON: Receives event information from the fields which receive a focus or click.
***/
tbfunction_pgTBObjSet( tbName, "user", tbName, 20); //Send user event to field with focus (little delay is good here)

//OR to set a global variable
focusField = tbName; //focusField is now a global variable which contains name of last focused field name.

tbfunction_caretPosition( tbName, "end" );
]]>
</function>
</make>

A note about variables in XML/JavaScript:
  • To set a local and/or global variable inside an XML/JavaScript function:
    var theField = tbName; //theField is now a LOCAL variable available ONLY within the function itself.
    myField = tbName; //myField is now a GLOBAL variable available everywhere in your application.
  • To retrieve the variable in your Actions code you have to use PowerPac's exeJavascriptDirect() function because the Actions Editor doesn't readily make global variable accessible unless they were set by the Actions Editor. And even then the variable names will be encrypted and it doesn't make sense to try and figure out their encrypted names. So to use the PowerPac to retrieve the global variable in Actions code:
    exeJavascriptDirect( "return myField;" ); store return value in tmp;
    Comment: Now tmp contains the value of your global myField.
    Comment: I recommend making tmp a LOCAL variable or you will have unnecessary globals scattered all over the place.
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Re: Click Event on input field

Postby Andy » Thu Jun 13, 2019 11:37 am

This all sounds good and is pretty cool!
So I reference the <make> section using an XMLHttpRequest on Load Book, right?
Andy
 
Posts: 47
Joined: Tue Sep 09, 2014 3:40 pm

Re: Click Event on input field

Postby Clifton » Thu Jun 13, 2019 1:01 pm

No, not exactly. You must include your tags in a fully styled XML document. The PowerPac includes predesigned templates to help you.
    Go to the PowerPac menu > Create/Edit File ... > XML Document > (choose template)
Enter all your tags like the ones we've been showing in these posts, then save the document
    Generally, you should create at least one XML document for each page of your book which uses the XML features.
    Please browse the XML Configuration section of this forum to become familiar with the information that can/should appear in XML documents.
    https://pgsoftwaretools.com/forum/viewforum.php?f=16
    I generally name my XML documents using the same name as the pages of my book. If you do this the XML documents and your page names should generally not contain spaces in their names as this can causes issues for some servers.
While you can load XML documents on load book, if the document contains page-related tags, then XML documents must be loaded on load page for the document containing the tags that apply. You can also load XML documents for the on load background event, though doing this on load page is usually the preferred event.

Here is a typical action to load your XML document for a single page of your book. You can call these actions as many times as needed to load all your XML's. The example below is dynamic and loads the XML document which corresponds to the name of the current page.
    Image 1.png
    XMLHttpRequest() to load XML Documents
    Image 1.png (13.56 KiB) Viewed 3947 times

Finally, you must use the PowerPac Export Tree Manager to add your XML documents to your project. I usually put them in a sub-folder in my book directory and name the folder xml. Then I just flag the entire folder to be included in the export. That way no matter how many XML documents I create, they will all get exported without having to flag each one individually. The example above is set to look for XML documents in the xml folder of the export.
 
Clifton
Site Admin
 
Posts: 732
Joined: Tue Jan 14, 2014 1:04 am

Next

Return to Web (DHTML) Development

Who is online

Users browsing this forum: No registered users and 2 guests

cron