Obviously, the effect is very practical. For this effect, we do not explain how to use the effects library, but how to create a similar effect and keep it usable, unobtrusive, and maintainable (so that future maintainers do not need to modify you In the case of scripts, modify images, appearance or text labels).
Step one: Analyzing the problem
To create a good script, the first step should be to analyze what you want to accomplish: we want to create a photo slideshow effect, and we Want to keep maintenance easy.
How to create a slideshow effect
There are several ways to have a slideshow on a website:
Include all images in the document.
This is a safe choice when running without JavaScript. Moreover, when the page is loaded, all images will be loaded as well. However, this method only works for a small number of images.
Includes the first image in the document and has a server-side script that creates a slideshow function.
This is also quite secure, but for the end user it is very annoying - as I don't want to load the whole page just to get the next photo. But it is more effective for page display and ad clicks, which is why a large number of news sites use this method.
Includes the first image in the document and loads additional images on demand.
What annoys you about this method is that it must rely on JavaScript and have a JavaScript array that maintains the photo list. You also need to provide a loading indicator to show the user something is going on.
In our case we take the list of pictures below, turn it into a slideshow effect using the forward and backward buttons, and an indicator that tells us, which photo out of the total number of photos is currently displayed.
The final output will look like the example slideshow effect.
Dependency Check
We have some elements here that depend on JavaScript generation: text indicators and forward and down links. To keep our solution usable, we need to ensure a few things:
These elements should only appear if JavaScript is available (the functionality that users trust us to provide them with). A link cannot do anything to violate the trust our users place in us.
Interactive elements should be available regardless of input device (let’s not rely on whether the user has a mouse).
Images should not be hidden unless the user can access them again. Technically, showing only the first image without forward and backward links is a fallback, but why should the user have downloaded all the images and only see the first one?
Step 2: Planning the Script
Once you have assessed the problem and picked out the solution you want to use, you can start planning the script. Essentially, our script should do this:
Check if the slide list exists and contains some images (is there a reason to create a slideshow effect for an image?).
Hide all photos but not the first one.
Create forward and backward links, and an indicator showing where we are.
Add an event handler to make the link increase or decrease the currently displayed image number.
Make sure the slide effect does not exceed the range. When the picture number is less than 0, it should become the last picture, and vice versa.
Different Functional Handling
We have some ways to handle this problem. One of them is to use the DOM to iterate through each LI entry and hide it. In this event listener function, we first hide the previously displayed LI (if any) and display the current one.
Note: Showing and hiding LI instead of images makes more sense, as it allows maintainers to add other elements to each slide, such as some titles.
The problem with this method is that we are making the necessary style changes in JavaScript, which means that if there is a need for more complex style changes than just changing the display from block to none in our script, the script will become More disorganized (no separation of performance from behavior).
Styles are left to the CSS parser
A cleaner approach is to leave all appearance changes (hiding some of the list items after all list items have been downloaded) to the browser's CSS parser. In our example, we can use a CSS rule in the slideshow to easily hide all list items and override the style of the current item with a specific class.
HTML:
"
img src="img/flat3.jpg" alt="Bathroom" />
-
CSS :
#slideshow li{
display:none;
}
#slideshow li.current{
display:block;
}
The only one The problem is that if we make CSS and JavaScript disabled, visitors will never be able to access the other images. Therefore, we need to apply these styles only when JavaScript is available. The trick is, when JavaScript is available, apply a class on the UL of the slide, e.g. named js . This allows us to display effects only when JavaScript is available, by simply modifying it in CSS:
CSS:
#slideshow.js li{
display:none;
}
#slideshow.js li.current{
display:block;
}
This class’s hook can also be used to provide static and dynamic versions of the slideshow A completely different look.
All our script needs to do is show and hide the current and previous photos by removing or adding the current class.
To ensure that our script will not affect other scripts on the same page, we will create a main object and construct all methods and properties on it. This ensures that our init() function will not be overwritten or override any other function with the same name.
JavaScript:
slideshow = {
current:0, // Current slide encoding
init:function(){
// Initialization and settings Event handling function
},
show:function(e){
// Event listener
}
}
The third step, basic tool method (Essential Tools)
Now, we have a framework for planning and building our script. It's time to think about some of the tools we need to accomplish this functionality. At its minimum, a DOM script's helper library should include:
A way to register an event handler, we'll currently be using John Resig's addEvent() method.
Methods to add and remove CSS style names.
A method that overrides the default behavior of HTML elements. We don't want the link's target page to appear, just execute the script.
We add these utility methods to the main object and get started:
JavaScript:
slideshow = {
current:0, // Current slide Coding
init:function(){
// Initialize and set up the event handler function
},
show:function(e){
// Event listener
},
addEvent:function(obj, type, fn) {
if (obj.attachEvent) {
obj['e' type fn] = fn;
obj[type fn] = function( ){
obj['e' type fn]( window.event );
obj.attachEvent('on' type, obj[type fn] );
} else
obj.addEventListener( type, fn, false );
},
removeClass:function(o,c){
var rep=o.className.match(' ‘ c)?' ‘ c:c;
o.className=o.className.replace(rep,”);
},
addClass:function(o,c){
var test = new RegExp(”(^|\s)” c ”(\s|$)”).test(o.className);
if(!test){o.className =o.className?' ‘ c:c;}
},
cancelClick:function(e){
if (window.event){
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (e && e.stopPropagation && e.preventDefault){
e.stopPropagation();
e.preventDefault();
}
}
}
当文档完全载完,第一件事情就是需要执行 init() 方法:
JavaScript:
slideshow = {
current:0, // 当前幻灯片编码
init:function(){
// 初始化和设置事件处理函数
},
show:function(e){
// 事件监听器
},
addEvent:function( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e' type fn] = fn;
obj[type fn] = function(){
obj['e' type fn]( window.event );
}
obj.attachEvent('on' type, obj[type fn] );
} else
obj.addEventListener( type, fn, false );
},
removeClass:function(o,c){
var rep=o.className.match(' ‘ c)?' ‘ c:c;
o.className=o.className.replace(rep,”);
},
addClass:function(o,c){
var test = new RegExp(”(^|\s)” c ”(\s|$)”).test(o.className);
if(!test){o.className =o.className?' ‘ c:c;}
},
cancelClick:function(e){
if (window.event){
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (e && e.stopPropagation && e.preventDefault){
e.stopPropagation();
e.preventDefault();
}
}
}
slideshow.addEvent(window,'load',slideshow.init);
Step 4: Script (The Script)
Now, we have all the method tools in place, and when the window is loaded Calling init() , we can begin to instantiate this method.
Note: This is only the init() method, not the entire script. Because of the line numbers, copying and pasting the script will result in an error.
1: init:function(){
2: if(document.getElementById && document.createTextNode){
3: var list = document.getElementById(' ');
4: if(list){
5: slideshow.items = list.getElementsByTagName('li'); if(slideshow .all > 1){
8: slideshow.addClass(list, ‘js’); }
12: slideshow.show();
13: }
14: },
Line 2, detects whether DOM is supported.
Line 3 and 4, try to retrieve the element with ID slideshow. If it is not defined, the remaining methods will not be executed.
Lines 5 and 6 retrieve the list items and the number of list items, and store them in the attributes items and all respectively.
Line 7 checks whether there is one more list item. If there is not too many list items, the rest will not be executed.
Line 8, add the js style class name to the list, thereby hiding the list items and the styles that should be different.
Line 9, call createNav() and provide this list as a parameter.
Line 12, call show() to display the sliding door with the predefined current attribute. The
createNav() method uses a DOM script to create the HTML required for the slideshow to work properly.
1: createNav:function(o){
2: var p = document.createElement('p');
3: slideshow.addClass(p, 'slidenav') ;
4: slideshow.prev = document.createElement('a');
5: slideshow.prev.setAttribute('href', '#');
6: var templabel = document.createTextNode ('<<');
7: slideshow.prev.appendChild(templabel);
8: slideshow.addEvent(slideshow.prev, 'click', slideshow.show);
9: p.appendChild(slideshow.prev);
10: slideshow.count = document.createElement('span’); );
12: slideshow.count.appendChild(templabel);
13: p.appendChild(slideshow.count);
14: slideshow.next = document.createElement('a');
15: slideshow.next.setAttribute('href', '#');
16: var templabel = document.createTextNode('>>');
17: slideshow.next.appendChild(templabel );
18: slideshow.addEvent(slideshow.next, 'click', slideshow.show);
19: p.appendChild(slideshow.next);
20: o.parentNode.insertBefore(p , o);
21: },
Lines 2 and 3, just create a P element to contain the entire slide navigation, and apply a class named slidenav.
Line 4 and 5, create a new link element, store it in an attribute called prev, and set the href attribute to #. It is necessary for the link to appear as a real link and for the keyboard to be enabled.
Line 6 creates a new text label.
Line 7, add the text label to the link.
In line 8, add an event handling function pointing to the show() listening method.
Line 9, add a new link to the paragraph.
Line 10, starting the counter, we create a SPAN element and store it with the count attribute.
Line 11, creates a new text node to display the position of the current slide in the total. We need to add 1 to the current attribute because human counting starts at 1 and not at 0.
Line 12, add the text as a new child node to SPAN.
Line 13, add the SPAN element to the paragraph.
Lines 14 to 19 are basically copies of lines 4 to 9. The only difference in recreating the link this time is the text label, which is stored in the next attribute.
Line 20, inserts the recently created paragraph before the initial picture list in the document.
All the tags created are necessary, and all that is left is to define a listener method show() that is called when the link is clicked.
1: show:function(e){
2: if(this === slideshow.next || this === slideshow.prev){
3: slideshow. removeClass(slideshow.items[slideshow.current], 'current');
4: var addto = (this === slideshow.next) ? 1: -1;
5: slideshow.current = slideshow. Current addto;
6: if (slideshow.current & lt; 0) {
7: Slideshow.current = (SlideShow.all-1);
8: 🎜> 9: if (SLIDESHOW. current > slideshow.all-1){
10: slideshow.current = 0; ) ' / ' slideshow.all);
14: slideshow.count.replaceChild(templabel, slideshow.count.firstChild);
15: slideshow.addClass(slideshow.items[slideshow.current], 'current' ;
Line 2, detects whether the clicked element is a downward or forward link (this is returned by addEvent()).
Line 3, remove the current class from the currently displayed slide. This will be possible since there is now a clicked link.
Line 4, by comparing this and next attributes, determine whether the current counter should be increased or decreased.
Line 5, correct the counter.
Lines 6 to 11, determine that the counter will never go out of range, when you are on the first slide and click the forward link, it will be set to the last, and when you are on the last slide, click For backward links, it will be set to the first one.
Lines 13 and 14, generate a new counter text and replace the old one.
Line 15 displays the new current slide by setting a class named current.
Line 16, prevent the default behavior of the link by calling cancelClick().
These are all the contents of the script. Now this script works, but it's still not really maintainable.
Step 5: Easing Maintenance
The script is fully functional, decoupled and impeccable. The real problem is that it's not easy to maintain now.
Perhaps the biggest problem with script applications is that not all maintainers understand JavaScript and are willing to look for parts of your script that need modification.
To prevent maintainers from doing this, the safest way is to separate the naming and IDs used in scripts and CSS from your script functionality. Also, it's a good idea to separate the text labels from the scripts used, since they may change. For example, when a script is localized in another language.
Reuse of tool methods
The first thing to do is to separate the utility functions from the main script that can be reused by other scripts. This is probably where most JavaScript libraries start.
tools.js:
/* Helper method */
tools = {
addEvent:function(obj, type, fn) {
if ( obj.attachEvent ) {
obj['e' type fn] 🎜> 🎜> },
removeClass :function(o,c){
var rep=o.className.match(' ' c)?' ' c:c;
o.className=o.className.replace(rep,”);
},
addClass:function(o,c){
var test = new RegExp(”(^|\s)” c “(\s|$)”).test(o.className) ;
if(!test){o.className =o.className?' ' c:c;}
},
cancelClick:function(e){
if (window.event){
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (e && e.stopPropagation && e.preventDefault) {
e.stopPropagation() ;
e.preventDefault();
}
}
}
CSS class and ID - Appearance
The next step is to separate the appearance class and ID into a separate include file. Make sure they are safe in the slideshow namespace, as other scripts are unlikely to use them. Nor does it get in the way of writing a brief explanatory note.
slideshow-css.js:
slideshow.css = {
/*
These are the classes and IDs used in slide effects.
You can modify any of them here.
Be sure to use quotes around the name and end it with a comma (except for the last one).
*/
showID :'slideshow',
dynamicClass :'js',
slideNavigationClass :'slidenav',
currentClass :'current'
}
Text labels - explained to the end user
Last but not least, let’s put the text labels into a separate include file, again using the slideshow namespace.
slideshow-labels.js:
slideshow.labels = {
/*
These are text labels used in slide effects.
You can modify any of them here.
Be sure to use quotes around the name.
There is no comma at the end.
*/
previous : '<<',
next : '>>',
counterpider : ‘ of ‘
}
Change the main script
We then need to modify the main script to use this information instead of relying on the embedded data. Not a lot of changes, easily done with search and replace.
slideshow.js:
slideshow = {
current:0,
init:function(){
if(document.getElementById && document.createTextNode ){
var list =document.getElementById(slideshow.css.showID);
if(list){
slideshow.items = list.getElementsByTagName('li'); > slideshow.all = slideshow.items.length;
if(slideshow.all > 1){
tools.addClass(list, slideshow.css.dynamicClass);
slideshow. createNav(list);
}
}
slideshow.show(); p');
tools .addClass(p, slideshow.css.slideNavigationClass);
slideshow.prev = document.createElement('a');
slideshow.prev.setAttribute('href', '#');
var templabel = document.createTextNode(slideshow.labels.previous);
slideshow.prev.appendChild(templabel);
tools.addEvent(slideshow.prev, 'click', slideshow.show);
p. appendChild(slideshow.prev);
slideshow.count = document.createElement('span');
templabel =document.createTextNode((slideshow.current 1) slideshow.labels.counterpider slideshow.all);
slideshow.count.appendChild(templabel);
p.appendChild(slideshow.count);
slideshow.next = document.createElement('a');
slideshow.next.setAttribute('href' , '#');
var templabel = document.createTextNode(
slideshow.labels.next);
slideshow.next.appendChild(templabel);
tools.addEvent(slideshow.next, ' click', slideshow.show);
p.appendChild(slideshow.next);
o.parentNode.insertBefore(p, o);
},
show:function(e){
if(this === slideshow.next || this === slideshow.prev){
tools.removeClass(slideshow.items[slideshow.current],
slideshow.css.currentClass);
var addto = this === slideshow.next ? 1 : -1;
slideshow.current = slideshow.current addto;
if(slideshow.current < 0){
slideshow.current = (slideshow.all-1);
slideshow .current = 0; .count.replaceChild(templabel, slideshow.count.firstChild);
tools.addClass(slideshow.items[slideshow.current], slideshow.css.currentClass);
tools.cancelClick(e);
}
}
tools.addEvent(window,'load',slideshow.init);
These are all files needed to ensure that future maintainers can work with your script without having to trouble you. The file name should be obvious, what it is, and over time, become a standard script: