Q. about validating/formatting user input

Jan Schenkel janschenkel at yahoo.com
Fri Oct 4 01:05:00 EDT 2002

--- Alex Rice <alex at mindlube.com> wrote:
> In Cocoa/ObjC there is this concept of NSFormatter,
> which both 
> validates user input from a text field, and also
> formats display of the 
> content. Is there any similar thing in Rev?
> In Rev, what I am thinking about doing is using the
> keyDown message and 
> regex matching to validate the input and allowing or
> disallowing the 
> keystroke that way. However, how can one extent that
> to entire classes 
> or textfields. Seems like it would involve a
> property and using the 
> message path, and I have an idea, but haven't been
> using rev long 
> enough... what's the most elegant way to do this?

Hi Alex,

Just thought I'd chime in on this one, as it's a topic
I've been working on lately. Here's a script for
numeric fields (copy&paste this time, so none of my
infamous typos ;-)


local sBeforePaste

on keyDown pWhichKey
  put the selectedChunk into tChunk
  put word 2 of tChunk into tStart
  put word 4 of tChunk into tStop
  if tStart > tStop then
    put (char 1 to tStop of me) & pWhichKey into \
    if length(me) > tStart then
      put (char tStart to -1 of me) after \
    end if
    put (char 1 to tStart - 1 of me) & pWhichKey \
      into tCheckString
    if length(me) > tStop then
      put (char tStop + 1 to -1 of me) after \
    end if
  end if
  if Conv4Calc(tCheckString) is a number then \
    pass keyDown
  else beep
end keyDown

-- field formatting
on closeField
  send "formatField" to me in 5 milliseconds
  pass closeField
end closeField

on formatField
  put the text of me into tNumber
  put Conv4Disp(Conv4Calc(tNumber)) into me
end formatField

-- handle paste in field
-- NOTE :: doesn't work when Rev UI is ON
on pasteKey
  put the text of me into sBeforePaste
  send "checkAfterPaste" to me in 5 milliseconds
  pass pasteKey
end pasteKey

on checkAfterPaste
  put the text of me into tAfterPaste
  if Conv4Calc(tAfterPaste) is not a number then
    put sBeforePaste into me
  end if
end checkAfterPaste

-- convert to and from MC/RR number format to display
-- format
function Conv4Calc pNumber
  -- strip out the thousand separators (if any)
  put the uThousandSeparator of me into t1000Sep
  if t1000Sep is not empty then replace t1000Sep \
    with empty in pNumber
  -- change the decimal point to a period
  put the uDecimalPoint of me into tDecPoint
  if tDecPoint is not empty and tDecPoint is not \
    "." then replace tDecPoint with "." in pNumber
  -- should now be a regular number for MC/RR
  -- calculations
  return pNumber
end Conv4Calc

function Conv4Disp pNumber
  -- convert to the chose floating point format
  put the uFormat of me into tFormat
  if tFormat is empty then put "%16.2f" into tFormat
  put format(tFormat, pNumber) into tNumber
  -- remove leading spaces
  replace " " with empty in tNumber
  -- split up the number into the sign, integer and
  -- decimal part
  local tMinusHold, tMainNumber, tDecimalHold
  get matchText(tNumber, \
    "([-]?)([0-9]*)[\.]?([0-9]*)", tMinusHold, \
    tMainNumber, tDecimalHold)
  -- tweak tDecimalHold
  put the uDecimalPoint of me into tDecPoint
  if tDecPoint is empty then put "." into tDecPoint
  if tDecimalHold is not empty then put tDecPoint \
    before tDecimalHold
  -- insert the thousand separators
  put the uThousandSeparator of me into t1000Sep
  if t1000Sep is not empty then
    -- determine how many separators to place
    put length(tMainNumber) into tLength
    put (tLength DIV 3) into tSeps
    if (tLength MOD 3) = 0 then subtract 1 from tSeps
    repeat with i = tSeps down to 1
      put t1000Sep before char - (i * 3) of \
    end repeat
  end if
  -- finally put it all together
  return tMinusHold & tMainNumber & tDecimalHold
end Conv4Disp

uFormat = the format in admittedly a C-style ; check
  the format-function in the Trascript Dictionary
  (defaults to "%16.2f")
uDecimalPoint = the decimal point to display ; a lot
  of countries in Europe use a comma
  (defaults to ".")
uThousandSeparator = the separator between thousands ;

  some people don't want any, others a space, others a
  comma, and Europeans may want a period to complement
  their decimal comma
  (defaults to none)


As for extending it to entire classes of textfields,
that's quite a different matter. It's on my to-do
list, but I think one could do quite a bit by using
the "frontScript" feature.
After revising the script above so that all references
to "me" are properly changed to "the target" and its
properties, we could move that into a field of its own
in a library stack.
Then we could 'activate' this script in any field by
setting its script to:

on openField
  insert the script of field "NumericInputOnly" of \
    card 1 of stack "myLib" into front
end openField

on closeField
  remove the script of field "NumericInputOnly" of \
    card 1 of stack "myLib" from front
end closeField

(Note that this is untested, so I could be off by the
length of a small football field)

Long post, but I hope it helped.

Best regards,

Jan Schenkel.

"As we grow older, we grow both wiser and more foolish at the same time."  (La Rochefoucauld)

Do you Yahoo!?
New DSL Internet Access from SBC & Yahoo!

More information about the Use-livecode mailing list