SCRIPTING:

Nina Brosh
THE ULTIMATE STRING TICKERS
A set of commonly requested scripts, achieved through synthetic codes. All the string tickers, namely text scrollers, you may want.
They can print on a form field or paint onto a layer or scroll on the status bar (if you still like the status bar scrolling, which I would rather discourage).
They scroll in continuous smooth loops, though you can stop them. They can scroll upward or downward, rightward or leftward: thus you can implement whatever amount of "scrolling news" or functionalities that could be better served by a scrolling process.
February 2004
{ @ }
The model above is Nina Brosh
LOADS OF NINA BROSH ON THE NET


WHY THESE SCROLLERS ARE BETTER
There is a reason I feature these scrollers

Tickers is a fashionable way to call text scrollers. And text scrollers are those texts that appear gradually, scrolling either right ward or left ward and either up ward or down ward within a target field. Though many times used out of context, none the less there are many occasions when a scroller is precisely the most suitable way to feature content in a way consistent with a well arranged GUI (general user interface): a typical example are small texts highlighting news which, for instance, can be stopped on mouse over and that may contain links to more comprehensive documentations.

The main feature of any scroller is that it must be recursive, namely upon finished a scrolling process, it must be able to restart in a coherent way sporting a smooth behaviour without sudden jumps or juggling.
The scrollers I feature here have manifold reasons to be preferred upon any other script for this purpose that can be currently found online.
  • A scroller that goes leftward uses the same codex for the scrollers that go upward, and a scroller that goes rightward uses the same codex for a scroller that goes downward. Many scripts simply missed this implication, without noticing that the process is still the same and all just depends on the type of parameters passed to the process.
  • Another reason, these scrollers are definitive as far as coding is concerned; it is in fact just nearly impossible to devise something more elegant and more brief that the dashing simplicity of this statement and the alike:
    input.push(input.shift());
    to make the scroller proceed.
  • These scrollers, with the same codes, can print on just whatever target support whether it is:
    • A layer
    • A form field
    • The status bar (which I won't recommend: scrollers are meant to be useful and visible, not nifty but useless. Moreover the status bar is meant to show other much more relevant data, and you're just obstructing the final user of one prerogative when you scroll on the status bar. Yet, with these scrollers you can just address whatever target, that is.)
  • These scrollers are all instances of a class, thus the encapsulation of the names is total: you can initialize as many scrollers as you want being assured that they won't populate the window scope with endless variable names.
  • You can consequently trigger all of your scrollers at once, if desired, or stop all of them at once: each of them is an independent instance of the class template!
  • The limitation of the parameters: no useless variables are created.
  • No need of trailing or leading empty spaces to make them look smooth: you can still provide your inputs with leading or trailing empty spaces if you like, yet this is not critcal for the mission and they scrollers will just go on being smooth anyway.
The scrollers are composed of two functions (not unlike, for instance, the image zoomers): one named makeTickers to initialize as many of them as you prefer and at once, the other, named tickerComponent which is the class that endows each initialized scroller with all the functionalities that every scroller must have.

The scrollers include the following methods:
  • Scroll leftward: method name is firstOff
  • Scroll rightward: method name is lastOff
  • Scroll upward: method name is firstOff
  • Scroll downward: method name is lastOff
  • Emulate a typing machine without pauses between lines: method name is typer
  • Emulate a typing machine with pauses between lines and dropping previous lines: method name is typer2
  • Emulate a typing machine with pauses between lines and preserving previous lines: method name is typer2
If you wish so, you can locate in the code the methods mentioned above (but not other methods with other names!) and if you think you don't need them you can even delete them manually from the code (being sure you don't miss deleting the closing curly bracket of each method or other mistyping of course). Be warned that if you delete typer you cannot use typer2 any longer as well (but not viceversa). typer2 is arguably a method you don't want: I added it in case you were looking for some functionality like that one (more details further on).

An ample test form to play with all of them is at bottom of this file. Now your codes:


THE CODES
The codes and how to initialize your scrollers

A Van Gogh painting
A Van Gogh painting: Anvers under the rain, (1890)
lines:
A Van Gogh painting
A Van Gogh painting: Cornfield with a view on Arles, (1888)

To initialize your scrollers you call in makeTickers.
The function requires only one mandatory argument: an array of string names. The array can have whatever length, from 1 onward. Such names must be unique name identifiers that you want to use for your scrollers (like when you assign variable names, precisely).
The function will encapsulate all these string names as properties of a globablly defined variable named "tickers" (namely such variable is within the window scope): namely if you have an array like:
var myarray=new Array("foo1", "foo2");
then:
makeTickers( myarray )

By then the makeTickers function has build up a family of variables encapsulated in the holding variable named "tickers" in the shape of:
tickers.foo1
tickers.foo2

of course you can also address them with the associative alternative syntax:
window['tickers']['foo1']
window['tickers']['foo2']


Each of such objects is an instance of the tickerComponent class, namely is an object upon which you can trigger its own scrolling methods.
If by chance you don't like the name "tickers" for your globally defined variable that gathers all the scrollers, pass to makeTickers a second argument as a string carrying the name you'd prefer. Of course if you do so, since then you will address the scrollers of this family no longer like tickers.foo1 but like yourNewName.foo1 (assuming you also passed "foo1" as one of the names arrayed in the input array passed as an argument).

AVAILABLE METHODS
setTarget( target, targetProperty )
After you have initialized your variables, a call to for instance:
tickers.foo1.setTarget(document.formName.formField, "value")
is a valid call to set the target of the scroller identified by tickers.foo1
Of course, every ticker must have a target to print upon. The setTarget method is indespensable to assign such target to the scroller; the first argument must be an object, the second argument a string:
  • Form field: provided your form has a name as formName and a field whose name is fieldName:
    tickers.foo1.setTarget(document.formName.fieldName, "value");

  • Layer: provided your layer as an id property set equal to, say, "myid":
    tickers.foo1.setTarget(document.getElementById("myid"), "innerHTML")

  • Status bar:
    tickers.foo1.setTarget(window, "status")
setTarget is case sensitive.
run( method, joiner, input, splitter, speed )
This method triggers a scroller. It would suffice passing its first argument, provided the input has been previously set; anyway the first argument is mandatory and must always be a string carrying the name of a scrolling method:
tickers.foo1.run( "lastOff" )

Valid method names are:
  • "lastOff"
  • "firstOff"
  • "typer"
  • "typer2"
I now describe in more detail the arguments listed in run():

method
As said, a string carrying the name of a method.
joiner
The functions will disaggregate whatever input string into an array. By setting how you rejoin it you can feature your method as horizontal or vertical scrolling.

Thus, if you want to scroll horizontally either on a layer or on a form field, pass joiner as an empty string:
""

If you want to scroll vertically on a layer, pass joiner as the html tag:
"<br>"

If you want to scroll vertically on a form pass joiner as an escaped newline command:
"\n"
TYPICAL joiner examples:

scroll horizontally:
tickers.foo1.run("lastOff", "", anInputString, "", 200)

scroll vertically on form:
tickers.foo1.run("lastOff", "\n", anInputString, " ", 200)

scroll vertically on layer:
tickers.foo1.run("lastOff", "<br>", anInputString, " ", 200)

lastOff or firstOff would both do: the former scrolls either rightward or downward, the latter either leftward or upward, depending exactly on which the joiner is.

Up/down ward scrollers should arguably be triggered passing splitter, as we do in the examples above, as a whitespace, so to divide the input string by words and not by mere letters. Anyway if you pass your input array not as a String but as an already formatted array of string entries (or with the splitters put into the points in your input string where you want it divided after, and the splitter property set exactly as such splitter), the up/down ward processes would print at each leap a whole entry exactly like you have crafted them.
input
The input text, as a string (though it would accept even an array of strings: in such case each leap of the scroller is a whole subsequent entry of the input array!)
splitter
If your input is a string, this must be the divider after which you want your string being divided and thus determine the leaping pace of the scroller: if you pass it as an empty string namely as
""
each single letter will be scrolled. If you pass for instance like an empty whitespace
" "
or as whatever else splitter prsent in the input string and thus suitable to make it explode into fragments, each fragment (instance: a whole word) will be the pace at which the scrolling process proceeds.
speed
A number, representing the speed in milliseconds of your scroller. Defaults to 250.

Of course, I could have added two more arguments to set the target and the target property to address, but I just didn't want to cluster it too much.
Thus, basically, once you have initialized a foo variable, just set the target first, and then call run with the arguments you wish to set.
runAll( method, joiner, input, splitter, speed )
Triggers run on all the scrollers gathered within tickers - or whatever other global holder variable name(s) you have declared.
Just invoke it from whatever instance, and it will affect all the instances gathered in the family:
tickers.foo.runAll("firstOff");
stop( fullReset )
It stops a scroller. If the argument is passed as number 1, it also reset all the defaults like speed, joiner (defaults to empty string), method (defaults to firstOff), the input (defaults to empty string) the target (defaults to null) and the targetProperty (defaults to "value").
stopAll( fullReset )
It triggers stop on all the scrollers for this family. You can call it from whatever instance.
isRunning
It is a property, not a method.
If it returns number 1, it means that the scroller is enagaged in a process.
run does not trigger if the scroller is already engaged, to avoid overlappings. A call to stop resets isRunning to zero.
isRunning is case sensitive.
A Van Gogh painting
A Van Gogh painting: Trees at dusk and a feminine shape, (1889)


Thus a typical set of invocations may look like:



Of course, if you prefer you may encapsulate the statements from input included downward within a third function to call upon some event (mouseovers, mouseouts, clicks etc...).

If you would use the method named typer2, you need to know a few details:
  • typer2 calls in typer
  • typer doesn't scroll, it just prints down the input (array) entry by entry simulating a typewriter machine. It is recursive, namely it restarts if not stopped.
  • typer2 calls in typer and varies it as follows:
    • As soon as the end of one entry in the input is reached it stops for a while depending on whether you have set a property named speed2, which defaults to 500 milliseconds (half a second) before typing the next entry:
      tickers.foo.speed2=300; /*or whatever*/
      tickers.foo1.run("tickers2", "", anInputString, "", 200)
    • Each time it tackles a new entry, it doesn't prepend the previous ones. If ou want to prepend also the previous ones declare prior to invoke it:
      tickers.foo.withPre=1;
A note: when printing onto a layer the tags that you may include within your string will be printed as active and real tags, thus you could for instance make scroll actual anchors or whatever type of html formatting you prefer.
Anyway be warned that if you split a string by, for instance, the empty spaces (white spaces), those tags that carry properties such as for instance:
< a href=&quoot;#">...
where, as you see, there is a white space bwteeen a and href, would obviously get truncated by such splitters.
The workaround for this is: insert in your strings splitters different than whitespaces and split after those: instance:

If you set the splitter to |, the tags won't be broken for they are not traversed by that splitter!

Of course, I am the first to agree that this is not the smoother way to achieve this: it is just a way, and in fact, being aware of this, I am going to provide you also with one more function named smartFormatter that can produce an array whose each entry is of a given length, without counting in in such length any html tags and while preserving such html tags in the output. Such function is at the next section, for now I'd just prefer you to get acquainted with the workings of the scrollers right now, without adding more data that at this point may appear confusing.

Anyway keep in mind that on march 2004 I am working on the auto looping self scrolling layers, which is a much better way to produce scrolling layers without touching at all the html formats within them. If you're reading this and it's no longer march 2004 that file is already completely ready, if it is still march it will still be incomplete as far as the layout is concenred though the codes will be in the html source.

First enjoy the test form, then feel free to skip to the next section for further details.


THE TEST FORM
Get familiar with your scrollers while having fun

A Van Gogh painting
A Van Gogh painting: Saintes Maries small street, (1888)
input:

format with smartFormatter? »
tickers.foo.setTarget( , property: )
tickers.foo.run( , joiner: , input, splitter: , speed: )
optional if you use typer2: typer2 settings:
speed2: withPre:
       
[ This scrolling process goes: ]
Textarea and layer: on click the scroller stops, on blur restarts.
A LAYER to print
A Van Gogh painting
A Van Gogh painting: Stone bench nearby the hospital at Saint Paul, (1889)


SMART FORMATTING OF A STRING WHICH INCLUDES HTML TAGS
A function that can produce, out of an input string, an array whose each entry is of the given length and that preserves the tags

One problem left out was the following: you have an input string, this input string contains html tags. You now want to produce out of this input string an array where the entries which are html tags are entries entirely on their own, and those which are just text as well, and of course the sequence they appear in the output array is the same sequence tags/plain text alternates in the input.

The function is named smartFormatter, and it takes in at most 3 arguments:
  1. Input: a String (though if an array, it would rejoin it after the next argument named splitter).
  2. Splitter: a String or whatever after which you want your input string being divided: it defaults to a white space, which is what arguably you wanted.
  3. maxLength: a Number; if you do not pass it, the function will just return an output array whose each entry are either an html tag or an isolated plain text segment.
    But if you do pass maxLength as a number higher than zero, the output will be composed of entries whose max length as far as plain text is concerned is the one dictated by your maxLength argument, exclusive of html tags which are included indeed, but are not counted in as far as the maxLength of an entry is concerned; this because html tags don't show up in a page as plain text, they only determine the format of the text which appears: thus they don't affect the length of a string but only its format.
With this function, you can surely create your arrays for your layer scrollers in a competent way.

One last problem left out was the possibility to include &nbsp; chars in an innerHTML to signify empty spaces. In an input array split char by char, they would turn into:
[&, n, b, s, p]
and that would cause problems, because the entity &nbsp; would be printed char by char as well, and thus will not be recognized as having a meaning as a whole.
If you were wondering about this, note this technique to allow the &nbsp; inputs as whole array entries in an array previously split char by char:



You have many ways to work around these things, if you keep in mind you can pass input also as an already fully formatted array, namely with whatever interpolations you may prefer among its entries.

A Joan Miro painting
A Joan Miro painting: Peinture, (1950)
smartFormatter codex
lines:
smartFormatter Test Form
Input:

splitter (hint: do not set it, is already whitespace):       maxLength: