<html>
<head>
<title> </ title>
<style>
#container {padding-top: 53px; padding-bottom: 3px; border: 1px solid gray; }
#container, #scroll div {width: 100px; }
#scroll, #scroll div {height: 50px; }
#scroll div {float: left; }
#container {position: relative; overflow: hidden; }
#scroll {position: absolute; top: 0px; width: 1000px; border-bottom: 1px solid gray; }
</ style>
<script>
/ *
* at the end of the topic
* /
</ script>
</ head>
<body>
<div id = "container">
<div id = "scroll" style = "left: 0px;">
<div style = "background: #ffc;"> page 1 </ div>
<div style = "background: #fcf;"> page 2 </ div>
<div style = "background: #cff;"> page 3 </ div>
<div style = "background: #fcc;"> page 4 </ div>
<div style = "background: #ccf;"> page 5 </ div>
<div style = "background: #cfc;"> page 6 </ div>
<div style = "background: #ccc;"> page 7 </ div>
</ div>
</ div>
<script>
/ *
* use
* /
</ script>
</ body>
</ html> // -
component = new SimpleScroll();
component.setContainer(document.getElementById("container"));
component.setScroll(document.getElementById("scroll"));
//
decorator1 = new Decorator_PageNum();
decorator1.setComponent(component); //
//
decorator2 = new Decorator_SwitchPage();
decorator2.setComponent(decorator1); //
decorator2.init();
decorator2.nextPage();component = new SimpleScroll();
component.setContainer(document.getElementById("container"));
component.setScroll(document.getElementById("scroll"));
component.init();
component.nextPage();component = new AnimScroll();
component.setContainer(document.getElementById("container"));
component.setScroll(document.getElementById("scroll"));
decorator1 = new Decorator_SwitchPage(); // new Decorator_PageNum();
decorator1.setComponent(component);
decorator1.init();
decorator1.nextPage(); // Component (interface)
// because of the scope, it will also set local variables and setters / getters to them - not academic, but not scary
// if there is a desire to use only prototyping, then it is necessary to create local variables "in place",
// and leave all functions that use them in Scroll empty
function Scroll () {
var container scroll;
this.setContainer = function (val) {
container = val;
};
this.setScroll = function (val) {
scroll = val;
};
this.getContainer = function () {
return container;
};
this.getScroll = function () {
return scroll;
};
this.init = function () {}; // manual initialization after setting the container and scroll
// this will simplify the task somewhat, since we will not need to rewrite the setters
this.nextPage = function () {}; // fast forward
this.prevPage = function () {}; // rewind back
this.hasNextPage = function (depth) {}; // presence of the next page, or the next depth pages; default depth = 1
this.hasPrevPage = function (depth) {}; // presence of the previous page, or the following depth pages; default depth = 1
this.findPages = function () {}; // return method number of pages
this.getCurPage = function () {}; // return method current page number
}
// ConcreteComponent (Component implementation)
// easiest scrolling
function SimpleScroll () {
var dublicate = this; // permanent link to the object being instantiated (for working with any this)
Scroll.call (this); // aggregate interface
// Scroll already knows how to work with container and scroll, but nothing more -
// now we need to implement (overload) all empty methods
var curPage = 0; // current page (0-4)
this.init = function () {};
this.nextPage = function () {
if (dublicate.hasNextPage ()) {
this.getScroll (). style.left = ++ curPage * -100 + "px";
}
};
this.prevPage = function () {
if (dublicate.hasPrevPage ()) {
this.getScroll (). style.left = --curPage * -100 + "px";
}
};
this.hasNextPage = function (depth) {
var depth = depth || one;
return curPage + depth <dublicate.findPages ();
};
this.hasPrevPage = function (depth) {
var depth = depth || one;
return curPage - depth> = 0;
};
this.findPages = function () {
return this.getScroll (). getElementsByTagName ("div"). length;
};
this.getCurPage = function () {
return curPage;
};
}
// ConcreteComponent (Component implementation)
// another scrolling, with animation
function AnimScroll () {
var dublicate = this; // permanent link to the object being instantiated (for working with any this)
Scroll.call (this); // aggregate interface
var curPage = 0;
var curOffset = 0; // current page offset in pixels
this.init = function () {};
this.nextPage = function () {
if (dublicate.hasNextPage () &&! curOffset) {
curPage ++; // add immediately to decorators work
curOffset = 0;
nextPageIterate ();
}
};
function nextPageIterate () {
curOffset - = 10;
dublicate.getScroll (). style.left = curOffset + (curPage-1) * -100 + "px";
if (curOffset> -100) {
window.setTimeout (arguments.callee, 20);
} else {
curOffset = 0;
}
}
this.prevPage = function () {
if (dublicate.hasPrevPage () &&! curOffset) {
curPage--;
curOffset = 0;
prevPageIterate ();
}
};
function prevPageIterate () {
curOffset + = 10;
dublicate.getScroll (). style.left = curOffset + (curPage + 1) * -100 + "px";
if (curOffset <100) {
window.setTimeout (arguments.callee, 20);
} else {
curOffset = 0;
}
}
this.hasNextPage = function (depth) {
var depth = depth || one;
return curPage + depth <dublicate.findPages ();
};
this.hasPrevPage = function (depth) {
var depth = depth || one;
return curPage - depth> = 0;
};
this.findPages = function () {
return this.getScroll (). getElementsByTagName ("div"). length;
};
this.getCurPage = function () {
return curPage;
};
}
// Decorator (interface)
// can encapsulate (save to a local component variable) a component or another decorator
// and just passes method calls to the component (except setComponent and getComponent)
function Decorator () {
var component;
this.setComponent = function (val) {
component = val;
};
this.getComponent = function () {
return component;
};
this.setContainer = function (val) {
return component.setContainer (val);
};
this.setScroll = function (val) {
return component.setScroll (val);
};
this.getContainer = function () {
return component.getContainer ();
};
this.getScroll = function () {
return component.getScroll ();
};
this.init = function () {
return component.init ();
};
this.nextPage = function () {
return component.nextPage ();
};
this.prevPage = function () {
return component.prevPage ();
};
this.hasNextPage = function (depth) {
return component.hasNextPage (depth);
};
this.hasPrevPage = function (depth) {
return component.hasPrevPage (depth);
};
this.findPages = function () {
return component.findPages ();
};
this.getCurPage = function () {
return component.getCurPage ();
};
}
Decorator.prototype = new Scroll ();
Decorator.prototype.constructor = Decorator;
// ConcreteDecorator (implementation of Decorator)
// buttons to switch pages
function Decorator_SwitchPage () {
var dublicate = this; // permanent link to the object being instantiated (for working with any this)
// connect the Decorator and write down references to the methods that are defined in Decorator's "interface" and which will be overridden here
Decorator.call (this);
var methods = {
nextPage: this.nextPage,
prevPage: this.prevPage,
init: this.init
};
var buttonNext, buttonPrev;
this.init = function () {
dublicate.getContainer (). appendChild (buttonPrev = createButton ("<", dublicate.prevPage));
dublicate.getContainer (). appendChild (buttonNext = createButton (">", dublicate.nextPage));
buttonNext.disabled =! dublicate.hasNextPage ();
buttonPrev.disabled =! dublicate.hasPrevPage ();
return methods.init ();
};
this.nextPage = function () {
buttonNext.disabled =! dublicate.hasNextPage (2);
buttonPrev.disabled =! dublicate.hasPrevPage (-1);
return methods.nextPage ();
};
this.prevPage = function () {
buttonNext.disabled =! dublicate.hasNextPage (-1);
buttonPrev.disabled =! dublicate.hasPrevPage (2);
return methods.prevPage ();
};
function createButton (text, onclick) {
var ret = document.createElement ("button");
ret.appendChild (document.createTextNode (text));
ret.onclick = onclick;
return ret;
}
}
// ConcreteDecorator (implementation of Decorator)
// current page indicator
function Decorator_PageNum () {
var dublicate = this; // permanent link to the object being instantiated (for working with any this)
Decorator.call (this);
var methods = {
nextPage: this.nextPage,
prevPage: this.prevPage,
init: this.init
};
var text;
this.init = function () {
dublicate.getContainer (). appendChild (text = document.createTextNode ("..."));
var ret = methods.init ();
chText ();
return ret;
};
this.nextPage = function () {
var ret = methods.nextPage ();
chText ();
return ret;
};
this.prevPage = function () {
var ret = methods.prevPage ();
chText ();
return ret;
};
function chText () {
text.nodeValue = "" + (dublicate.getCurPage () + 1) + "/" + dublicate.findPages ();
}
} function cr () {
var ret, last;
for (var i = 0, l = arguments.length; i <l; i ++) {
ret = new arguments [i] ();
if (! i) {
ret.setContainer (document.getElementById ("container"));
ret.setScroll (document.getElementById ("scroll"));
} else (
ret.setComponent (last);
}
last = ret;
}
return ret;
} <table cellpadding = "5"> <tr> <th> workWith </ th> <td> = </ td> <td> <div> <input type = "radio" name = "component" value = "simple" id = "component-simple" checked = "checked" /> <label for = "component-simple"> SimpleScroll </ label> </ div> <input type = "radio" name = "component" value = "simple" id = "component-anim" /> <label for = "component-anim"> AnimScroll </ label> </ td> <td> + </ td> <td> <input type = "checkbox" id = "pageNum" checked = "checked" /> <label for = "pageNum"> pageNum </ label> </ td> <td> + </ td> <td> <input type = "checkbox" id = "switchPage" checked = "checked" /> <label for = "switchPage"> switchPage </ label> </ td> </ tr> </ table> <button onclick = "create ();"> Recreate component with decorators </ button> <br /> <button onclick = "workWith.prevPage ();"> workWith.prevPage () </ button> <button onclick = "workWith.nextPage ();"> workWith.nextPage () </ button> <br />
var component;
var decorator1;
var decorator2;
var workWith;
function reset () {
component = decorator1 = decorator2 = workWith = null;
var node = document.getElementById ("scroll");
node.style.left = "0px";
while (node.nextSibling) {
node.parentNode.removeChild (node.nextSibling);
}
}
function create () {
reset (); // reset previous settings (if any)
// create component - basis for further work
if (document.getElementById ("component-simple"). checked) {
component = new SimpleScroll ();
} else {
component = new AnimScroll ();
}
component.setContainer (document.getElementById ("container"));
component.setScroll (document.getElementById ("scroll"));
workWith = component;
if (document.getElementById ("pageNum"). checked) {
// create the first decorator
decorator1 = new Decorator_PageNum ();
decorator1.setComponent (component); // wrap the component in the decorator
workWith = decorator1;
}
if (document.getElementById ("switchPage"). checked) {
// create another decorator
decorator2 = new Decorator_SwitchPage ();
if (decorator1) {
// wraps the first decorator in the second
decorator2.setComponent (decorator1);
} else {
// wrap the component in the decorator
decorator2.setComponent (component);
}
workWith = decorator2;
}
workWith.init ();
}
create (); Source: https://habr.com/ru/post/65219/
All Articles