PURPOSE OF THE SCRIPT
|
|
What the script does, how the idea came to my mind
|
The idea for this script came while I was thinking about some PHP interfaces.
A PHP script would have queried a SQL database drawing from it a set of possible answers. For each of them it was required to build a complex HTML interface showing all the properties (SQL fields) of each record, so that for each found record the same HTML formal module would have been repeated, yet filling each of these formally identical html modules with different data.
Thus I thought that to help the users, I could have added to each module a layer that would have carried, with some catching design, a description of the specific topic of each module so to make easier for the user to identify as soon as possible what differentiated a module from the other or what a html module was about when compared with another apparently analogous html module.
Since the modules were lengthy, the idea was to allow this eye catching component to scroll within the module, maybe within sort of a track of its own, as soon as the user, scrolling the whole page, reached the level of a module; this scrolling layer would have had to accompany the user's sight as long as the scrolling process was within the limits of each given module, and not beyond those.
This is basically a somewhat improved version of what time ago was popular after the name of watermarks (the geocities times - instance of a page referring to those times and to that watermark here) , though these are multiple "watermarks" that can be arranged to move only within the limits of specified containers namely within the boundaries of other layers wrapping the scrolling layer - though nothing would prevent you from setting a whole document wide containing layer so to implement a traditional page "watermark"; moreover the fact you can nest your scrolling layer within other layers adds a considerable amount of flexibility in a page layout as you'll see also in the test form below.
The javascript I feature here achieves precisely this.
A Raphael painting: Galatea
|
While elaborating it I stumbled across a set of potentially manifold caveats, so that I eventually devised the shape that met less problems.
All these potential caveats were not issues related to the script, but to the way browsers dealt with css (style sheets positioning and padding and position offsets calculations): in several occasions, while developing it, I met situations where, for instance, Internet Explorer did what was expected but Netscape or Firefox didn't, and vice versa.
Though you will find many persons who would insist that it would have been mainly either this browser's or that browser's fault whenever we encounter problems at dealing with Style Sheets in the expected way, the truth is: all browsers exhibit quirk behaviours in nearly the same degree, and I find it is rather pathetical an approach to web scripting that somewhat popular approach that invests even browsers with an ideological stance: since men live symbolically, even browsers become, in a few persons' opinion, the new incarnation of evil, if not, which happens quite frequently, of - badaboooom- capitalism.
I can't explain to you what a sense of annoyance I feel whenever I find this attitude in an interlocutor and this portrait of the standards set by the World Wide Web Consortium
as if they would have been or sensed as the equivalent of a resolution of the United Nations, with all the relative emotional imports about "international legality" and how pivotal it would have been to abide by it: politics and fundamentalism even till within the choice of a browser, raising a bagatelle as a browser to the level of an ontological symbol!
I find this pitiable and miserable indeed.
So when I will explain to you here a few things that you must caution yourself about when at using this script in order not to meet browser related (and not script related) issues, it is never imported any political stance whatsoever: I don't have this need to discharge political hysteria continuously by inventing or by "hyping" the targets.
YOUR CODES
|
|
The codes, later how to use them
|
First your codes, then I will describe how to use them and I will feature the relative test form.
By the way, if you are using other scripts from this website, do not meddle with this script, onto the same layers, other scripts like for instance the drag a layer and the resize a layer scripts.
lines (with comments and blank lines):
A Edward Hopper painting
|
HOW THE SCRIPT WORKS
|
|
How to initialize the script, how to draft your layers
|
The script is a class, but you have to follow these rules to initialize it:
- You can initialize only one instance of this class per page, and one alone (so called singleton).
- The name of the variable you must initialize is preassigned, that is you can use only the following name:
menuMaster
and no one else.
The reason is that the class relies on setting timeouts, and in javascript timeouts cannot trace back from within their codes a class instance by keyword this, thus I had to hard code within the class a few lines with the name of the class written down in plain text. And such name is, exactly, menuMaster.
-
You must perform the initialization either soon before the closing </BODY> tag, or soon after it (which is legitimate).
This because the script calculates layer offsets, and such offsets are not fully rendered by a browser if the whole page has not been parsed yet because the browsers suspend all the eventual results when reckoning offsets of top and left positions until a whole picture of all the layers present in a document has been gathered. Only then a browser can safely tell the offsets.
Keeping in mind these banal rules of thumb, the initialization is therefore precisely as follows:
var menuMaster = new wrappedMenu();
If you pass no arguments (or you pass zero) to that constructor, the default scrolling with the layer you will add (you'll see soon how) will be of making them scroll only if a vertical scrolling of the page intercepts them ( by far the most typical case indeed).
If you pass as argument number 1, only horizontal scrolling will be considered.
If you pass number 2 both vertical and horizontal scrolling will be considered as affecting all the added layers - instance:
var menuMaster = new wrappedMenu();
As you'll see, you have class methods to change this behaviour for specific layers if you want to set exceptions.
A George Owen Wynne Apperley painting, Enigma.
|
Before I explain to you how to add layers after you have initialized the singleton, so that they will all be sliding as soon as a page scrolling intercepts them and insists within their range, I have to explain to you how you must craft these layers.
The rules are:
- There must be a layer (or more of course, if you want more sliding menus) which is meant to be your sliding "menu".
Such layer must have an id of your choice, as long as it is unique - as all ids should be. Instance:
<div "dunno"> ... </div>
The script will take care to autoset the position of this layer to absolute.
- Each of such layers must have an outermost containing layer that wraps it. An id is not indispensable for this latter layer. Yet it is also possible to nest more menus within one single wrapping layer, but the point is: a menu(s) must have a wrapping layer, and that's the point.
Example:
<div style="position: relative">
<div "dunno"> ... </div>
</div>
Each of these containers can of course take full advantage of the css formatting power: for instance if you set a width for your wrapped layer, you could set to the wrapping layer a css property:
padding-left:nestedLayerWidth_here + nestedLayerLeft_position + nestedLayer_maybe_paddings;
so to implement a setting where your nested layer scrolls as if it had a whole left empty track of its own to scroll within, while the text included in the wrapping layer flushes on the right margin of the container.
So playing with the css properties of both the nested menu and the wrapping layer entirely resides on your own fantasy or needs. I can assure you that with a little bit of css effort, this set of two nested layers can be inserted within nearly any desired overall layout setting.
Caveat: do not add to this layer borders: to add borders see further on the trick.
- such wrapping layer must have a css position
declared - either as position:absolute or as position:relative.
- Such wrapping layer should not have borders set (as for margins, check on more browsers to be sure), or the wrapped menu could mismatch.
To add decorations to this layer you should rather wrap this whole set of two layers within another third layer that can then include whatever css settings except position declarations (see next point).
- This wrapping layer cannot be wrapped in any other layer (no other layer!) whose css position is declared in any fashion.
Though this may seem a severe limitation, there are not really overall layouts that you can't implement with a bit of savvy css coding.
Yet you do can wrap those layers within other outermost layers as long as these further tiers have no css position declared, though they can declare any other css property.
Instance:
<div style="padding: 10px;">
<div style="position: relative">
<div "dunno"> ... </div>
</div>
</div>
- Between the wrapper layer and the wrapped layer there must be no interposed innermost containing html tag, so the following would be wrong:
<div style="position: relative">
<strong>
<div "dunno"> ... </div>
</strong>
</div>
That is, there is an innermost layer, then a wrapper layer.
Outside this last layer there can be if (if) you want a set of further containing layers but only as long as these latters have no css position declared.
Ok?
The reason this became necessary is exactly that, with a triple (or higher) nesting level whereas one of the layers above the second tier from within (nesting the wrapper, that is) has a css position declared, one of those weird handling of css by browsers intervenes: offset positions cannot be calculated appropriately any longer - as for why, query the wind: maybe page and layers offsets derivation is counted in from the top left angle of the outermost nesting and css postioned element, yet even if you scan all the parent nodes and cumulate the offsets to retrieve the overall offsets relative to the document top left angle, you'll end up with the (usually badly) wrong offset results all the same.
This set of nested layers can be safely accommodated, if you wish so, within a table cell for instance.
It can be nested within anything actually, as long as above the wrapper nothing that contains (that nests, namely) this set of already nested layers ( wrapper plus wrapped menu; or, in other words, nothing that wraps the wrapper itself) has a css position declared.
CLASS METHODS
|
|
The class available methods and how to add layers.
|
Provided you have arranged your set of nested layers and your layer that must scroll has an id, here are your methods. The method named addLayers is the one that includes scrolling layers to your page.
- menuMaster.addLayers(speed, layers);
This method includes your scrolling layers into the page.
The first argument must be the speed you want to set, in milliseconds. Defaults to 250, which suffices.
After that you pass the ids of the wrapped layers, either as a list or as an array or even as an alternation of both. Example:
menuMaster.addLayers(200, "id1", "id2" );
Beware: the main error when using this method is forgetting that the first argument must not be a layer id but a speed numerical value.
- menuMaster.isAdded(layerId);
This returns boolean true if the id layer passed as argument corresponds to a layer that has been added, otherwise it returns boolean false.
menuMaster.isAdded("id1");
- menuMaster.changeSpeed(speed, layers);
This allows you to change on the fly, if you need it, the scrolling speed of an already added layer.
Arguments: the same instructions as for addLayers.
menuMaster.changeSpeed(200, "id1", "id2" );
- menuMaster.changeScroll(scrollType, layers);
This allows you to change on the fly, if you need it, the scrolling type of an already added layer.
Arguments: the same instructions as for addLayers, except that the first argument must be zero if you want a vertical only scrolling, 1 if you want a horizontal only scrolling, 2 if you want both.
menuMaster.changeScroll(2, "id1", "id2" );
- menuMaster.removeLayers(layersIds);
This removes on the fly a layer from the scrolling ones. The removed layer(s) would, of course, scroll no longer.
They can be added back, if you wish so, by using on them addLayers again.
Arguments either a list of layer ids, or an array, or even an alternation of both.
menuMaster.removeLayers("id1", "id2" );
The class has then two internal private methods that are the layer engines, and are named runY (alias: run) and runX.
THE TEST FORM
|
|
A small test form where you can get acquainted with the class functionalities.
|
Here is a test form. Not really all possibilities are included, and of course not all css possible combinations are included, yet it is useful to start seeing how it works.
You have two scrolling layer, nested within two relatively positioned wrappers.
Remember that you must initialize your class and therefore add your layers soon before or after the closing body tag, and nowhere earlier.
As for how they get initialized, the statement is as simple as follows:
</BODY>
<SCRIPT>
menuMaster=new wrappedMenu();
menuMaster.addLayers(100, "menu1", "menu2", "menu3");
</SCRIPT>
So, basically, all that you have to code is the css of the wrapped layers (which could be basic as well as complex, depending on your fantasy too actually), accordingly to the guidelines previously outlined. The only problems you can find entirely depend on browsers different implementations of css, regardless of the fact the css statements you use should have been implemented all in the same way - they just aren't, thence the probable necessity (which can not be ascribed to my script) to devote some time and some cross browser testing to them, which is actually also fun and is not really a demanding scripting task requiring any particularly sophisticated professionality.
Of course, there is an increasingly popular tactic which consists in introducing into your css rules a few things called css hacks [ a css hacking discussion page, or a very interesting article: Molly Holzschlag on Css hacking. These links provide you with a good starting point about the current css hacking debate].
Css hacks are basically intentionally nonsensical expressions, belonging to no standard or codified or let alone recommended synopsis and that get included within css rules, and which are deliberately designed to fool browsers that do not parse a css statement in the expected way so to induce them to ignore the css rule they can't handle, or to mistake it for something else.
This css hacking evolved in sort of a pseudo mini programming language of its own - say like regular expressions did, with the difference that regular expressions are not twists imposed onto a script.
I refuse to consider css hacking an option (links above do not sponsor it, they describe it), though if you like it or you know it you can definitely resort to it: but in my opinion (personal opinion, and nothing more) a feature that doesn't work the expected way should be abandoned and not fixed by purposely inserting bugs or marketed via scripts that include, propose and propagate them as the upbeat solution of to-day; web scripting should never neglect itself to the degree of advisedly becoming an exercise of necromancy.
This is an outermost NON css positioned layer. This is useful to include decorations, such as borders or padding, which should not be set inside the wrapping layer, which is the blue one inside.
If the background color would have been the same than the blue wrapper within, no one would realize it is another layer that gives the paddings and the border decorations!
I'm an independently nested layer.
Meaningless duis autem vel eum iriure dolor in henderit vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit ague duis dolore te feugait nulla facilisi.
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.
Accumsan et iusto feuer deleguit focusque phantasorum disliquet, occasum elevuit potentissima rovit. Damae solaque voracier tolunum, estollat consequia veriamque domani rogati.
Etiam tiem supurrius, orenio, et velerrimum devenit; tomacque aramis demerius valenuritude idaque conjure. In foedere pactum tempestae forgenit aschewed romaqui. Faremus polestis festina lente, et domasti coravi comcuisque voreni.
I'm utterly meaningless I just imitate latin.
This is an outermost NON css positioned layer. This is useful to include decorations, such as borders or padding, which should not be set inside the wrapping layer, which is the blue one inside.
If the background color would have been the same than the blue wrapper within, no one would realize it is another layer that gives the paddings and the border decorations!
Meaningless duis autem vel eum iriure dolor in henderit vulputate velit esse molestie consequat, vel illum dolore eu feugiat nulla facilisis at vero eros et accumsan et iusto odio dignissim qui blandit praesent luptatum zzril delenit ague duis dolore te feugait nulla facilisi.
Nam liber tempor cum soluta nobis eleifend option congue nihil imperdiet doming id quod mazim placerat facer possim assum.
Accumsan et iusto feuer deleguit focusque phantasorum disliquet, occasum elevuit potentissima rovit. Damae solaque voracier tolunum, estollat consequia veriamque domani rogati.
Etiam tiem supurrius, orenio, et velerrimum devenit; tomacque aramis demerius valenuritude idaque conjure. In foedere pactum tempestae forgenit aschewed romaqui. Faremus polestis festina lente, et domasti coravi comcuisque voreni.
I'm utterly meaningless I just imitate latin.
Given the way css implementations on different browsers can vary, you do have to test on more browsers (I suggest at least IE5+ and Netscape5+ and maybe Opera - no Netscape 4 compatibility is available), you will have to introduce minor changes. For instance, you will see that you should not set an overflow property, and that the height of the outermost non css positioned possible further wrapping layers must exceed a bit the height of the included ones.
A Claude Monet painting.
|
|