PDA

View Full Version : Multi-Part Content script



gracilis
03-18-2005, 07:40 AM
hi folks

can anyone help me to add more than one scipt of this Multi-Part Content script (DD->dynamic content) on ONE page (e.g. box1 box2 etc.).

i tried to use 'numbered' functions
e.g.
cycleforward
cycleforward1

for box 1 and box 2

but either text form link 2 changed in box one or no links in box 2 were visible.

thanx
tom
:cool:

jscheuer1
03-18-2005, 07:51 AM
Numbering the functions is good, do that to all the variables, id names, anything unique to the script too, if you are thorough it will work. The name of the game is, don't let anything in one version of the script affect the other version.

mwinter
03-18-2005, 01:13 PM
Numbering the functions is good, do that to all the variables, id names, anything unique to the script too, if you are thorough it will work. The name of the game is, don't let anything in one version of the script affect the other version.Time would probably be better spent rewriting the script after reading my treatise on creating re-usable scripts (http://www.dynamicdrive.com/forums/showthread.php?t=1666). Of course, it would need more work than that:


var createMultipartSection = (function() {
var getElementById;

if(!Array.prototype.push) {
Array.prototype.push = function() {
for(var j = 0, n = arguments.length; j < n; ++j) {
this[this.length] = arguments[j];
}
return this.length;
};
}

if(document.getElementById) {
getElementById = function(id) {return document.getElementById(id);};
} else if(document.all) {
getElementById = function(id) {var r = document.all;
if(('number' == typeof r.length) && r.tags) {
for(var j = 0, n = r.length; j < n; ++j) {
if(r[j].id == id) {return r[j];}
}
} else if(r.id == id) {return r;}
return null;
};
} else {getElementById = function() {return null;};}

function getParts(ancestor) {
var elements = ancestor.getElementsByTagName
? ancestor.getElementsByTagName('*')
: ancestor.all ? ancestor.all : [],
r = [];

for(var j = 0, n = elements.length, c, cN; j < n; ++j) {
c = elements[j]; cN = c.className;
if(('string' == typeof cN) && /(^|\s+)multipart-part(\s+|$)/.test(cN)) {
r.push(c);
}
}
return r;
}

function showElement(element, show) {
if(element.style) {element.style.display = show ? '' : 'none';}
}

return function(id, loop, navProvided, start) {
var current = start || 0,
next = loop
? function() {return cycle(1);}
: function() {return move(1);},
previous = loop
? function() {return cycle(-1);}
: function() {return move(-1);},
back, forward, parts, section;

function cycle(delta) {
showElement(parts[current], false);
current = (current + delta + parts.length) % parts.length;
showElement(parts[current], true);
return false;
}

function move(delta) {
if(((current + delta) < parts.length) && ((current + delta) >= 0)) {
showElement(parts[current], false);
current += delta;
showElement(parts[current], true);
showElement(back, current != 0);
showElement(forward, current != (parts.length - 1));
}
return false;
}

if((section = getElementById(id)) && (parts = getParts(section)).length) {
if(navProvided) {
back = getElementById(id + '-back');
forward = getElementById(id + '-forward');
} else if(document.createElement && document.createTextNode
&& document.body && document.body.appendChild)
{
var n = document.createElement('ul'),
b = document.createElement('li'),
f = document.createElement('li');

back = document.createElement('a');
forward = document.createElement('a');

if(n && b && back && f && forward && n.appendChild) {
n.id = id + '-navigation';
back.id = id + '-back'; back.href = '#';
forward.id = id + '-forward'; forward.href = '#';

back.appendChild(document.createTextNode('Back'));
b.appendChild(back);
n.appendChild(b);

forward.appendChild(document.createTextNode('Forward'));
f.appendChild(forward);
n.appendChild(f);

document.body.appendChild(n);
} else {back = forward = null;}
b = f = n = null;
}
if(back && forward) {
back.onclick = previous;
forward.onclick = next;
showElement(back, current != 0);
showElement(forward, current != (parts.length - 1));

for(var j = 0, n = parts.length; j < n; ++j) {
if(j != current) {showElement(parts[j], false);}
}
}
}
};
})();

The code above creates a function, createMultipartSection, which takes four arguments:


id - A string containing the id attribute of an element which is the ancestor of a group of parts. Required.
loop - A boolean which indicates whether the parts should be navigated in a cyclic or linear fashion. Defaults to false (linear).
navProvided - A boolean which indicates whether createMultipartSection needs to create navigation controls or if they are already in the document. Defaults to false (create).
start - A number specifying which part to show first. Defaults to zero (0).
If the navigation generation feature isn't used, the code should work with IE4+ and any DOM supporting user agent (Opera, Firefox, Safari, etc). If the navigation generation feature is used, the script will not work with IE4 as it doesn't possess a particularly useful document.createElement method. That said, the script is currently untested, but it should work.

The behaviour of the script has changed, and does have new features.


The class name which parts should use is [i]multipart-part. This can be changed by editing the regular expression in the getParts function. The use of a regular expression for class name matching also allows for the use of multiple class names rather than only one.
The expected naming of the navigation elements is based upon the id passed as the first argument. The navigation container should have the id, id-navigation, the back control should have id-back, and the forward control should have id-forward. If the navigation elements are generated, they will follow the same pattern so you can reliably style them.
The generated navigation controls will be in the form of an unordered list, inserted at the end of the document. A basic CSS rule for styling them would be:


#id-navigation {
list-style-type: none;
margin: 1em 0;
padding: 0;
}
#id-navigation li {
display: inline;
margin: 0;
padding: 0 1ex;
}You can, of course, add things such as absolute positioning. Adjust as you see fit. If you want to control your own placement, and what is used for the controls, specify true for the third argument and follow the pattern in the previous point.
The parts found during execution will be hidden automatically, with the exception of the starting part. They must not be hidden via a style sheet rule.


The function must be called after the containing element, its parts, and any provided navigation has been parsed by the user agent. Calling the function as part of a load event handler will obviously accomplish this, but an earlier call is possible.

Have fun, :)
Mike

jscheuer1
03-18-2005, 05:13 PM
Thanks for the rewrite, Mike! I must have been slipping up, as I usually start a message like my previous one in this thread with language stating that it is better to rewrite the script to get it to perform the new tasks. That treatise is something else though. I noticed the author is the only one to reply to its thread. I read it through once, seems very useful except hard to understand. I know Mike usually knows what he is talking about even if we don't. Similarly, this rewrite above seems a little difficult to understand but, at least I think I got it on the first read through (own ignorance showing through). I feel as though I, or someone, should take on the task of being Mike's voice in matters relating to humans. That being said, code loads up real nice on a blank page. I've downloaded the original script's content and will try plugging it in to see if I can make it do something. Too bad we don't have the content from the person who started this thread to play with.

jscheuer1
03-18-2005, 06:05 PM
I set the above rewrite up, as per instructions, assuming I understood them. Seems to work fine except that I cannot seem to avoid this type of layout on the page:

Section containing first set of content

Section containing second set of content

controls for 1st section

controls for 2nd section

any suggestions?

our work is at:
Rewrite MultiPart Content (http://home.comcast.net/~jscheuer1/side/multi.htm)

mwinter
03-18-2005, 07:14 PM
Thanks for the rewrite, Mike!You're welcome. :)


I must have been slipping up, as I usually start a message like my previous one in this thread with language stating that it is better to rewrite the script to get it to perform the new tasks.Particularly if you're trying to introduce such a radical change. A non-trivial script that wasn't designed to be used more than once could never be so easily adapted.


That treatise is something else though.Hmm. Should I take that as a compliment? :D


I noticed the author is the only one to reply to its thread. I read it through once, seems very useful except hard to understand.That's why I posted again, hoping to get questions. I've had at least five attempts at explaining closures, and that's about the best one so far (I think). It really isn't an easy thing to do, especially writing for a general audience.


Similarly, this rewrite above seems a little difficult to understand [...]I would normally heavily comment something as complicated as that, but I ended up writing it in the reply text area, rather than in jEdit. It was awkward enough due to the restricted space.


[...] I think I got it on the first read throughAs always, if something needs an explanation, just ask. If really necessary, I'll edit the post and comment the lot.


I feel as though I, or someone, should take on the task of being Mike's voice in matters relating to humans.Oh. Cheers for that! :rolleyes: :p


That being said, code loads up real nice on a blank page.Well, it doesn't really do much except create a few functions unless you invoke the function.


Too bad we don't have the content from the person who started this thread to play with.I'd have tested the code myself, then. To be honest, I was feeling lazy as I had other things on my mind. If I wasn't reasonably sure that it would work, then I would have set up an example.

There's currently only one change that I have in mind, which would provide a better solution to the positioning problem. Instead of passing a boolean for the third argument (create controls), the code could require a function instead. This callback could allow the user to create and insert the controls anywhere, and anyhow they chose. If the argument was null or omitted, the code could attempt to find pre-included controls. It's easy to implement, but not so simple to use as the author must know how to manipulate the document tree.


I set the above rewrite up, as per instructions, assuming I understood them. Seems to work fine except that I cannot seem to avoid this type of layout on the page:

Section containing first set of content

Section containing second set of content

controls for 1st section

controls for 2nd section

any suggestions?A couple of points:


Remove the id attribute on the inner div elements, with the exception of the last in each table which should really have the value checker-navigation and checker2-navigation respectively.
Call the createMultipartSection function with the third argument set to true. This will cause it to find and use your navigation components. For example,


function load() {
/* Don't loop. Use existing navigation. */
createMultipartSection('checker', false, true);
createMultipartSection('checker2', false, true)
}

<body onload="load();">
Don't hide the div elements containing the navigation links. Also, there's no need to set actions for the links: a handler will be added automatically.

The style sheet suggestions I made were only useful if you allowed the code to add navigation controls itself. Also, if you didn't want the controls to appear at the bottom, position them using CSS.


That would change the mark-up to something like:


<table id="checker" width="350">
<tr>
<td>
<div class="multipart-part">
<img src="files/photo1.jpg" align="left">
<p>Blah, blah, blah...</p>
</div>
<div class="multipart-part">
<img src="files/photo2.jpg" align="left">
<p>Blah, blah, blah...</p>
</div>
<div class="multipart-part">
<p>Blah, blah, blah...</p>
</div>
<div id="checker-navigation" style="width: 250px">
<a id="checker-back" style="float: left"
href="#"><img src="files/35.gif" border="0"> Back</a>
<a id="checker-forward" style="float: right"
href="#">Forward <img src="files/36.gif" border="0"></a>
</div>
</td>
</tr>
</table>Again, untested.

Mike

jscheuer1
03-18-2005, 09:11 PM
Think I got all that. There are now two versions:

Links Removed, will reappear updated in later post

They generate phantom content while loading (IE6) but, that resolves itself once the page is fully loaded or read from cache. Not sure why. Time limited, for debugging right now.

jscheuer1
03-18-2005, 10:07 PM
Using IE6 I find that by marking inner div's (except the first) display:none it solves the problem but, think I am missing something that might have prevented that necessity. I have updated the online versions to reflect this latest change:

HTML controls - inner divs display:none (http://home.comcast.net/~jscheuer1/side/multif.htm)

Generated controls - inner divs display:none (http://home.comcast.net/~jscheuer1/side/multic.htm)

Looking at them in NS7.2 presented a new question, no phantoms but the HTML controls are not where I'd expect them to be. I can use the '!important' hack to get them lined up but, I'm sure you would have a better way. It is really IE6 that is parsing the css wrong to begin with.

mwinter
03-19-2005, 02:43 PM
I thought I should produce my own example (http://mwinter.webhop.info/dd/multipart/demo.html), so I did.

The script used there has changed to include the callback enhancement I mentioned. I also fixed a problem with the getParts function in IE 5.01/IE 5.5, altered the Array.push replacement slightly, and commented the code.

I've now tested the script in IE versions 4.01, 5.01, 5.5 and 6, plus Firefox 1.0 and Opera 7.54u1, and it works on all of them. However,


Control generation still won't work with IE4, for reasons previously mentioned.
IE 5.01 doesn't like the example at all, but that's due to its poor CSS support, not the script. Ironically, versions 4 and 5.5 are fine, though 4 doesn't do quite what it's supposed to. Still, it's not as broken as 5.
The overlapping images are due to the use of absolute positioning. I originally used float but that revealed a rather annoying bug in Firefox that I couldn't be bothered to find a workaround for. Though I did fix it initially, adding the second demonstration just brought it back again, so I gave up. :D I must remember to check Bugzilla (http://bugzilla.mozilla.org/) at some point to see if it's a known problem.


One other change is the expected control id values. Instead of the back and forward suffixes, the code now looks for previous and next. They're more appropriate adjectives, and it homogenizes the code.

I think that's it! :cool:

Mike

jscheuer1
03-19-2005, 07:51 PM
Nice work! One would think our original poster would have plenty to work with in tackling his/her objectives. I was thinking though that for someone like you or I who is comfortable using absolute positioning in laying out a page (either entirely or mixing it with other methods), this is all well and good. Can this rewritten script work like the one we are jumping off from, for folks who would rather not take that leap just yet? Looking back at DD's version, it appears that the placement of the initial division element determines where the multi-part content appears on a page and that only one short style declaration is required for content height. Can we emulate that simplicity, or go even further by having content entered into the script section and placement be determined by where, in the markup, we call the function from (rather than having it an onload event as it is in all versions so far including DD's)? I know that second part would be really tough. On a separate matter, I know what an 'em' is what's an 'ex', as in "padding: 1ex"?

mwinter
03-19-2005, 08:39 PM
Nice work! One would think our original poster would have plenty to work with in tackling his/her objectives.Actually, I was thinking: "Is the OP even reading all this?"


I was thinking though that for someone like you or I who is comfortable using absolute positioning in laying out a page (either entirely or mixing it with other methods), this is all well and good. Can this rewritten script work like the one we are jumping off from, for folks who would rather not take that leap just yet?I think you misunderstand. The absolute positioning is merely a replacement for floating the two images left. The first two paragraphs have an inset class applied to them. This specifies a large left margin so that the image can be inserted. If it weren't for the Firefox bug, all that would be necessary is a float and a few clear declarations. Both of these positioning schemes are specific to this example. They aren't requisite.


Looking back at DD's version, it appears that the placement of the initial division element determines where the multi-part content appears on a page [...]The same occurs here. All the script really does is show and hide a series of elements with a specific class name. It just does it in a scalable fashion, unlike the original.


On a separate matter, I know what an 'em' is what's an 'ex', as in "padding: 1ex"?It's another font-relative unit. Whilst em units reflect the full height of the font (1em equals the value of the font-size CSS property), ex units reflect the x-height; a font metric that defines the height of lowercase glyphs.

One last feature in the example that I forgot to mention was that the first section has parts which aren't children of the container. If you look, you'll see a nested div element. I didn't actually mean to leave it in, but I did use it for testing. Nevertheless it demonstrates that any descendant with the necessary class name will be considered for inclusion. That could allow for unique layouts, such as certain table cells within a table.

Mike

jscheuer1
03-19-2005, 11:06 PM
The absolute positioning is merely a replacement for floating the two images left. The first two paragraphs have an inset class applied to them. This specifies a large left margin so that the image can be inserted. If it weren't for the Firefox bug, all that would be necessary is a float and a few clear declarations. Both of these positioning schemes are specific to this example.I thought it might be something like that. Having come this far we should consider writing it up as a library page, in the format of:

Demo:

Developers View(link)

step 1:(textarea)

step 2:(example markup)

....however many steps

technical notes:

Darn, I really wish the OP had given us his/her content now.

Thanks for the explanation of 'ex' makes perfect sense, just never ran accross that measurement in a css declaration before.

gracilis
03-20-2005, 06:35 PM
Darn, I really wish the OP had given us his/her content now.

hi folk, thanx for the help. i really did (like in the first answer) create 4 pieces of the same functions (checking the counting...)

but in mozilla it doesn't look good.

the texts are about housebuilding, there are 4 styles for one house, so i want to shorten the text for each style. (classic, modern, country, mediteranian).

the site is in german, but you can see the 'boxes'. the functions are in the page itself.

http://www.rostow.de/haustest1.php (wait until loaded in frame).

will test your scripting. thanx tom.

jscheuer1
03-20-2005, 10:06 PM
To fix Mozilla you might try this:


<div id="formnavigation" style="width:150px; display:none">
<a id="backbutton" href="javascript:cycleback()" style="float:left">« Zurück</a>
<a id="forwardbutton" href="javascript:cycleforward()" style="float:right">Weiter »</a></div>only difference is the width, I remember it helped when I was testing things out. Play around with it, larger or smaller widths may prevent the wrapping that Mozilla is apparently adding. Looks like you are using my method for expanding the script, you might have better luck with Mike's final (so far) version but, be aware that his uses different naming for parts and navigation and different syntax for the HTML navigation markup.

mwinter
03-21-2005, 01:42 PM
<div id="formnavigation" style="width:150px; display:none">
<a id="backbutton" href="javascript:cycleback()" style="float:left">« Zurück</a>
<a id="forwardbutton" href="javascript:cycleforward()" style="float:right">Weiter »</a></div>I should probably point out that when floating content, one must explicitly specify the width of the element. This could be done with percentages - width: 50%; would mean each link would be 75px wide[1] - or more regular units such as em or px[2].

Though the explicit width limitation has been removed from CSS 2.1, that document is not yet a Recommendation and it remains a good idea to be explicit.

Mike


[1] Be careful when constructing layouts using percentages. Rounding errors can sometimes result in elements becoming slightly too large, so be less precise. 49.5% might be better for the previous example.
[2] Pixel units should not be used with regard to text layouts as they tend to introduce inflexibility when different user font preferences are encountered. Use them for something pixel-based like laying out content with respect to an image. Use em and ex for text.