Details

    • Type: New Feature New Feature
    • Status: Resolved
    • Priority: Trivial Trivial
    • Resolution: Won't Fix
    • Affects Version/s: 1.3.0-rc1
    • Fix Version/s: None
    • Component/s: wicket-extensions
    • Labels:
      None

      Description

      Allow developers to designate a keystroke input pattern for the input text component. The pattern would be used on the client to control valid keystrokes for the current cursor position within the input text field in relation to the specified pattern.

      For example, a pattern could be designated as "(999)9999" causing only number values in each position where a "9" appears and using the "(", ")", and "" as masking characters. When the cursor position reached one of these mask characters the cursor position would advance to the next "9" position. The resulting mask would appear as "(__)_-___" within the input text value.

        Activity

        Hide
        Will Hoover added a comment -

        Attached is the JS script I wrote to handle the mask on the client. There are no libraries needed to use it (it's self contained). All code is original except the trivial snippet at the bottom that is public domain that adds an escape feature to JavaScript's RegExp.

        Example usage (param1= input component, param2=mask, param3=clear the input text value when invalid):
        <input type="text" onfocus="javascript: InputTextMask.processMaskFocus(this, '(999)999-9999', true);" />

        /**

        • InputTextMask component script used for mask/regexp operations.
        • Mask Individual Character Usage:
        • 9 - designates only numeric values
        • L - designates only uppercase letter values
        • l - designates only lowercase letter values
        • A - designates only alphanumeric values
        • X - denotes that a custom client script regular expression is specified</li>
        • All other characters are assumed to be "special" characters used to mask
        • the input component
        • Example 1:
        • (999)999-9999 only numeric values can be entered where the the character
        • position value is 9. Parenthesis and dash are non-editable/mask characters.
        • Example 2:
        • 99L-ll-X[^A-C]X only numeric values for the first two characters,
        • uppercase values for the third character, lowercase letters for the
        • fifth/sixth characters, and the last character X[^A-C]X together counts
        • as the eighth character regular expression that would allow all characters
        • but "A", "B", and "C". Dashes outside the regular expression are
        • non-editable/mask characters.
          */
        Show
        Will Hoover added a comment - Attached is the JS script I wrote to handle the mask on the client. There are no libraries needed to use it (it's self contained). All code is original except the trivial snippet at the bottom that is public domain that adds an escape feature to JavaScript's RegExp. Example usage (param1= input component, param2=mask, param3=clear the input text value when invalid): <input type="text" onfocus="javascript: InputTextMask.processMaskFocus(this, '(999)999-9999', true);" /> /** InputTextMask component script used for mask/regexp operations. Mask Individual Character Usage: 9 - designates only numeric values L - designates only uppercase letter values l - designates only lowercase letter values A - designates only alphanumeric values X - denotes that a custom client script regular expression is specified</li> All other characters are assumed to be "special" characters used to mask the input component Example 1: (999)999-9999 only numeric values can be entered where the the character position value is 9. Parenthesis and dash are non-editable/mask characters. Example 2: 99L-ll-X [^A-C] X only numeric values for the first two characters, uppercase values for the third character, lowercase letters for the fifth/sixth characters, and the last character X [^A-C] X together counts as the eighth character regular expression that would allow all characters but "A", "B", and "C". Dashes outside the regular expression are non-editable/mask characters. */
        Hide
        Frank Bille Jensen added a comment -

        It looks nice. I will convert it into a component and if no-one objects I will add it to extensions.

        Show
        Frank Bille Jensen added a comment - It looks nice. I will convert it into a component and if no-one objects I will add it to extensions.
        Hide
        Gerolf Seitz added a comment -

        i played with it yesterday, and i think there are certain limitations to it:

        1) if you have a textfield with an integer model-object and you want to use a mask like "(999)999",
        the model will not get updated due to conversion failure.

        2) the InputTextMask doesn't handle prefilled textfiields (component has a non-null, length>0 modelobject)

        this is what i found out with just a little playing around, though these issues can be solved probably fairly easy (eg. override convertInput for 1))

        Show
        Gerolf Seitz added a comment - i played with it yesterday, and i think there are certain limitations to it: 1) if you have a textfield with an integer model-object and you want to use a mask like "(999)999", the model will not get updated due to conversion failure. 2) the InputTextMask doesn't handle prefilled textfiields (component has a non-null, length>0 modelobject) this is what i found out with just a little playing around, though these issues can be solved probably fairly easy (eg. override convertInput for 1))
        Hide
        Frank Bille Jensen added a comment -

        1) I would say the component needs a converter to handle those values. Who says that "(999)9999" or "9999-99-99" is an integer? IMO those could be both string, number and date.

        2) I haven't tried it yet, but if it's the javascript that doesn't handle it, then it should be fixed.

        Show
        Frank Bille Jensen added a comment - 1) I would say the component needs a converter to handle those values. Who says that "(999)9999" or "9999-99-99" is an integer? IMO those could be both string, number and date. 2) I haven't tried it yet, but if it's the javascript that doesn't handle it, then it should be fixed.
        Hide
        Will Hoover added a comment -

        1) As Billie stated- that was the intention to have "(999)999" evaluate as a string. Most masks should be evaluated a string seeing that most of the time a mask would contain special characters that define the mask (i.e. "(", ")", and "-" in the example). For special cases where a string needs to be converted (such as the case with a date) it would be just as easy to use a converter that converts a date based upon a regexp check on the server. If I am missing something let me know :o)

        2) To clarify, this is only an issue when a "invalid" prefilled value is provided. In which case, IMHO, is an issue with the data provided. If the user does not have a valid value to begin with then it's an issue with their data. However, the script does handle "valid" prefilled values. The script assumes that the initial value (if any) originated from a valid source (i.e. DB or other source).

        If this is really an issue that needs to be addressed...

        A) I could add a page load listener that would validate the value and handle conversion accordingly, but what would we do if an invalid value is found? notify the user and leave it as is (really doesn't resolve the issue)? clear the value (may confusing to developers to see their data missing)?

        B) We could do the validation on the server side before rendering the page- seeing that we already have the mask pattern at that point. Not to mention, we need to do the conversion (and possibly validation) going back to the server anyways, but this will duplicate our efforts in that the code used to evaluate/convert the value would exist on the server as well as the client.

        Show
        Will Hoover added a comment - 1) As Billie stated- that was the intention to have "(999)999" evaluate as a string. Most masks should be evaluated a string seeing that most of the time a mask would contain special characters that define the mask (i.e. "(", ")", and "-" in the example). For special cases where a string needs to be converted (such as the case with a date) it would be just as easy to use a converter that converts a date based upon a regexp check on the server. If I am missing something let me know :o) 2) To clarify, this is only an issue when a "invalid" prefilled value is provided. In which case, IMHO, is an issue with the data provided. If the user does not have a valid value to begin with then it's an issue with their data. However, the script does handle "valid" prefilled values. The script assumes that the initial value (if any) originated from a valid source (i.e. DB or other source). If this is really an issue that needs to be addressed... A) I could add a page load listener that would validate the value and handle conversion accordingly, but what would we do if an invalid value is found? notify the user and leave it as is (really doesn't resolve the issue)? clear the value (may confusing to developers to see their data missing)? B) We could do the validation on the server side before rendering the page- seeing that we already have the mask pattern at that point. Not to mention, we need to do the conversion (and possibly validation) going back to the server anyways, but this will duplicate our efforts in that the code used to evaluate/convert the value would exist on the server as well as the client.
        Hide
        Gerolf Seitz added a comment - - edited

        1) i used an integer model-object in my example, but as you said, the component would need a converter.
        2) yes, it is the javascript

        i tried to implement it as a behavior that expects the bound component to implement ITextFormatProvider to get the input mask,
        but i haven't found a way to "inject" a converter into the component form inside the behavior. maybe it was just too late

        update:
        william, these problems are probably easier to solve if there is a dedicated component (eg. MaskedTextField).
        as i said above, i tried the more "lightweight" approach to use the mask also for currently existing TextField subclasses (eg. DateTextField in wicket-datetime). in this case, you don't always have the luxury to say that the modelobject should be a string, since you can't alter the components internals from outside.
        maybe i'm just overlooking something and overcomplicating it, so i can be totally wrong.

        Show
        Gerolf Seitz added a comment - - edited 1) i used an integer model-object in my example, but as you said, the component would need a converter. 2) yes, it is the javascript i tried to implement it as a behavior that expects the bound component to implement ITextFormatProvider to get the input mask, but i haven't found a way to "inject" a converter into the component form inside the behavior. maybe it was just too late update: william, these problems are probably easier to solve if there is a dedicated component (eg. MaskedTextField). as i said above, i tried the more "lightweight" approach to use the mask also for currently existing TextField subclasses (eg. DateTextField in wicket-datetime). in this case, you don't always have the luxury to say that the modelobject should be a string, since you can't alter the components internals from outside. maybe i'm just overlooking something and overcomplicating it, so i can be totally wrong.
        Hide
        Frank Bille Jensen added a comment -

        I would go for the MaskTextField. Gerolf do you want to look further at this? Then just assign yourself. Else I will take a look at it this weekend.

        Show
        Frank Bille Jensen added a comment - I would go for the MaskTextField. Gerolf do you want to look further at this? Then just assign yourself. Else I will take a look at it this weekend.
        Hide
        Will Hoover added a comment -

        Seeing that the only issue that exists is in relation to prefilled "invalid" values...

        IMHO, I think that it can/should be done generically on the TextField component. All that would be needed is to verify that a valid regexp validator exists that supports the mask (remove reserved characters: "9", "L", "l", "A", and any characters that exist between the reserved regexp character "X"). Basically, this is how a type definition is declared on the TextField to begin with (minus the mask check)- is it not?

        Otherwise, a MaskTextField is fine, but I think it's just as easy to do it generically :o)

        Show
        Will Hoover added a comment - Seeing that the only issue that exists is in relation to prefilled "invalid" values... IMHO, I think that it can/should be done generically on the TextField component. All that would be needed is to verify that a valid regexp validator exists that supports the mask (remove reserved characters: "9", "L", "l", "A", and any characters that exist between the reserved regexp character "X"). Basically, this is how a type definition is declared on the TextField to begin with (minus the mask check)- is it not? Otherwise, a MaskTextField is fine, but I think it's just as easy to do it generically :o)
        Hide
        Gerolf Seitz added a comment -

        frank, if you want to, you can do it. i won't be able to do it this weekend.

        Show
        Gerolf Seitz added a comment - frank, if you want to, you can do it. i won't be able to do it this weekend.
        Hide
        Frank Bille Jensen added a comment -

        I weren't able to get around to it as well. Depending on what we figure out with the 1.3 release perhaps we postpone this until 1.4. Lets see.

        Show
        Frank Bille Jensen added a comment - I weren't able to get around to it as well. Depending on what we figure out with the 1.3 release perhaps we postpone this until 1.4. Lets see.
        Hide
        Sean Sullivan added a comment -

        Cool idea. I'd like to see this feature in Wicket

        Show
        Sean Sullivan added a comment - Cool idea. I'd like to see this feature in Wicket
        Hide
        Johan Compagner added a comment -

        frank, i am setting this now to 1.3 but move it to 1.4 if you can't get it right very soon.

        Show
        Johan Compagner added a comment - frank, i am setting this now to 1.3 but move it to 1.4 if you can't get it right very soon.
        Hide
        Gerolf Seitz added a comment -

        i just stumbled over iMask: http://zendold.lojcomm.com.br/imask/
        this could be a (very appealing) alternative to the attached implementation (no offense Will).

        although it requires mootools, maybe there's not much to do to remove this dependency.

        iMask is released under the terms of the MIT License.

        Show
        Gerolf Seitz added a comment - i just stumbled over iMask: http://zendold.lojcomm.com.br/imask/ this could be a (very appealing) alternative to the attached implementation (no offense Will). although it requires mootools, maybe there's not much to do to remove this dependency. iMask is released under the terms of the MIT License.
        Hide
        Will Hoover added a comment -

        no offense taken :o) Looks like a nice tool- Although, it is a little bloated. Is it possible to shrink it (as you proposed)? Also, the expected behavior of the backspace/delete keys are not what most user's would expect- I suppose that is customizable?

        Most of the bells and whistle features are pretty easy to add to the attached mask if desired (background color, cursor, etc.)

        Show
        Will Hoover added a comment - no offense taken :o) Looks like a nice tool- Although, it is a little bloated. Is it possible to shrink it (as you proposed)? Also, the expected behavior of the backspace/delete keys are not what most user's would expect- I suppose that is customizable? Most of the bells and whistle features are pretty easy to add to the attached mask if desired (background color, cursor, etc.)
        Hide
        Martin Grigorov added a comment -

        There is such component in WicketStuff - https://github.com/wicketstuff/core/tree/master/jdk-1.5-parent/mootools-meiomask-parent. it is available in Maven repos.

        Show
        Martin Grigorov added a comment - There is such component in WicketStuff - https://github.com/wicketstuff/core/tree/master/jdk-1.5-parent/mootools-meiomask-parent . it is available in Maven repos.
        Hide
        Martin Grigorov added a comment -

        There are integrations with third party JS solutions as I stated earlier.
        No need for more complex JS code in wicket modules.

        Show
        Martin Grigorov added a comment - There are integrations with third party JS solutions as I stated earlier. No need for more complex JS code in wicket modules.

          People

          • Assignee:
            Unassigned
            Reporter:
            Will Hoover
          • Votes:
            1 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved:

              Development