Native JS object-oriented idea encapsulates the Carousel diagram component

Source: Internet
Author: User

            Native JS object-oriented idea encapsulates the Carousel diagram component

In the front-end page development process, the Carousel map effect is very common in the page, so I want to encapsulate one of my own native JS carousel diagram components. With this demand began to prepare, of course, the code is concise as the goal, the implementation of the various functions of the carousel is divided into different modules. At present, this version of my package does not fit the mobile side, only the PC side.

  The main functions are : Automatic carousel, click on a picture corresponding to the small dot jump to the specified picture, there are front and rear toggle buttons. The use of the time only need to pass in the path of the picture and each picture of the corresponding jump path and the Target box ID can be, you can also customize the delay of each graph rotation, but the delay parameter is not required parameters, you can not specify the delay, using the default delay.

Here I used to replace the prototype object implementation of the way to implement the code, the following I detail the various modules I divided: The first is the initialization operation, followed by the page layout module, event binding module, automatic rotation and style binding module, there are some used in the encapsulation function, Finally, there is an AMD spec support setting. Words not much to say, directly on the code:

/** * Carousel Diagram Component * @param opts parameter list: Picture parameters picture Jump Path Carousel delay * @param targetid Target Box ID required * @constructor *///package to be real Now the uniqueness of each function function//pass a parameter w, reduce cross-scope lookup (function (w) {//unchanging content placed outside the constructor//template string var template = ' <div class= "W-slider" id=         "Js_slider" > ' + ' <div class= "slider" > ' + ' <div class= "Slider-main" id= "Slider_main_block" > ' + ' </div> ' + ' </div> ' + ' <div class= "Slider-ctrl" id= "Slider_ctrl" > ' + ' <s        Pan class= "Slider-ctrl-prev" ><</span> ' + ' <span class= "Slider-ctrl-next" >></span> ' +    ' </div> ' + ' </div> '; var imgstr = "<div class= ' slider-main-img ' ><a href= ' {{href}} ' ></a></    Div> ";    Default parameter var defaultopts = {time:2000}; /** * Add Event * @param target to who added * @param type of event type added * @param handler event handler */var Adde Vents = (function () {//capability checkTest if (window.addeventlistener) {return function (target, type, handler) {Target.addevent            Listener (Type,handler,false);        }; } else if (window.attachevent) {return function (target, type, handler) {Target.attachevent ("on            "+ type, handler);        };    }    })(); /** * Gets the property value of the style * @param obj * @param attr * @returns {*} return value with unit */var GetStyle = function (o        BJ, attr) {if (obj && obj.currentstyle) {return obj.currentstyle[attr];        } else {return getComputedStyle (obj, null) [attr];    }    };        function Carousel (Targetid, opts) {if (!targetid) throw new Error ("Please pass in the Target box");        This.targetid = document.getElementById (Targetid);        This.str = template;        This.targetId.innerHTML = This.str;        This.bigbox = document.getElementById ("Js_slider"); This.parentbox = document.getElementById ("Slider_main_block");        This.ctrlbox = document.getElementById ("Slider_ctrl"); opts = opts | |        defaultopts; Mixed inheritance to determine if the incoming opts has a value in the default parameter, if the default parameter value does not exist opts//The default parameter is added to the OPTs, so that the default parameters will not be modified for the (var k in defaultopts            {if (!opts[k]) {opts[k] = defaultopts[k];        }} for (Var k in opts) {this[k] = opts[k];              } This.timer = null;                  Total timer this.inow = 0;    Control the number of plays, which is the image of the This.init (); } Carousel.prototype = {Constructor:carousel,//Initialize page, event binding init:function () {this._            CreateNode ();            This._addevents ();        This.timer = SetInterval (This._autoplay (), this.time);            },//node generation, page Layout _createnode:function () {var _this = this;            var newimgstr = ""; for (var i = 0; i < this.imgData.length; i++) {//Generate Carousel Graph node Newimgstr + = Imgstr.replace ("{{href}} ', This.imgdata[i].href). Replace ("{{src}}", THIS.IMGDATA[I].SRC);                This.parentBox.innerHTML = Newimgstr;       This.imgs = This.parentBox.children;                Carousel image var img = this.imgs[0].getelementsbytagname ("img") [0];                Generate control button node var span = document.createelement ("span");                Span.setattribute ("Class", "Slider-ctrl-con");       span.innerhtml = This.imgdata.length-i;                Set the text content of a span for easy use behind This.ctrlBox.insertBefore (span, this.ctrlbox.children[1]);    Img.onload = function () {//Picture loaded completely after setting large box width high _this.scrollwidth = img.offsetwidth;  Large box width _this.scrollheight = img.offsetheight;                    Large box Height _this.bigbox.style.width = _this.scrollwidth + "px";                    _this.ctrlbox.style.width = _this.scrollwidth + "px";     _this.bigbox.style.height = _this.scrollheight + "px";               _this.ctrlbox.style.height = _this.scrollheight + "px";                    Set line height to picture height _this.prev = _this._getfirstelement (_this.ctrlbox);                    _this.next = _this._getlastelement (_this.ctrlbox);                    _this.prev.style.lineheight = _this.scrollheight + + + "px";                    _this.next.style.lineheight = _this.scrollheight + + + "px"; The first picture is in the original position and all the rest is moved to the right of the box for (var j = 1; J < _this.imgs.length, J + +) {_this.i                    Mgs[j].style.left = _this.scrollwidth + "px";            }                };            }//First highlight This.spans = This.ctrlBox.children;        This.spans[1].setattribute ("Class", "Slider-ctrl-con current");            },//Event binding _addevents:function () {var _this = this;       This.over = true; Throttle valve//Monitor Click event, traverse left and right arrows and lower box for (var k in This.spans) {//this.spaThe properties in NS contain 0-5 numbers and a length attribute, to exclude the length property if (k.length = = = 1) {addevents (this.spans[k], "cl                            Ick ", function () {//Click on the Left button if (this.classname = = =" Slider-ctrl-prev ") {                                if (_this.over) {_this.over = false;                                    _this._animateeffect (_this.imgs[_this.inow], {left: _this.scrollwidth}, Function () {                                _this.over = true;  }); Current picture right Shift--_this.inow < 0?                                _this.inow = _this.imgs.length-1: _this.inow;    _this.imgs[_this.inow].style.left =-_this.scrollwidth + "px";                                    The next picture moves quickly to the leftmost _this._animateeffect (_this.imgs[_this.inow], {left:0}, function () {                                _this.over = true;        });                     Next picture then move right           _this._setsquare (); }}//6. Click on the right button to move the current picture to the left, then a picture to the left, then move to the other side (This.clas                        SName = = = "Slider-ctrl-next") {_this._autoplay () ();  }//7. Click on the span below to start else {var that = this.innerhtml    -1;                                Save the index of the clicked Span first if (that > _this.inow) {////When the location of the clicked Span is to the right of the current span position, similar to clicking the right button     _this._animateeffect (_this.imgs[_this.inow], {left:-_this.scrollwidth});   The current picture moves left _this.imgs[that].style.left = _this.scrollwidth + "px"; The picture index is quickly moved to the far right of that, then left again} else if (that < _this.inow) {//when the clicked span position is to the left of the current span position, the class     _this._animateeffect (_this.imgs[_this.inow], {left: _this.scrollwidth}) appears to have been clicked.           Move the current picture right                     _this.imgs[that].style.left =-_this.scrollwidth + "px";        The image index is quickly moved to the far left of that, then right-_this.inow = that;                            Click on the current span _this._animateeffect (_this.imgs[_this.inow], {left:0});                        _this._setsquare ();                }                    }); }}//Monitor mouse Move-out event addevents (_this.bigbox, "mouseover", function () {Cleari                Nterval (_this.timer);                _this.prev.style.display = "block";            _this.next.style.display = "block";            });               Addevents (_this.bigbox, "mouseout", function () {clearinterval (_this.timer); To use the timer first clear//transfer the current this as a parameter to the function in the timer _this.timer = SetInterval (_this._autoplay (), _this.time                );                _this.prev.style.display = "None"; _this.next.style.display = "None";           });                },//Synchronize the current small square style _setsquare:function () {for (var i = 1; i < this.spans.length-1; i++) {            This.spans[i].setattribute ("Class", "Slider-ctrl-con"); }//inow is starting from 0, while Spans[0] is the left arrow, so inow+1 This.spans[this.inow + 1].setattribute ("Class", "Slider-ctrl-co        n current ");            },//Auto-Carousel, returns an anonymous function, passing the instance of this to the timer, the default timer in this is pointing to Window _autoplay:function () {var _this = this;                    return function () {if (_this.over) {_this.over = false;  _this._animateeffect (_this.imgs[_this.inow], {left:-_this.scrollwidth}, Function () {_this.over                    = true;     }); Current picture left shift ++_this.inow > _this.imgs.length-1?                    _this.inow = 0: _this.inow;         _this.imgs[_this.inow].style.left = _this.scrollwidth + "px"; The previous picture moves quickly to the far right _this._animaTeeffect (_this.imgs[_this.inow], {left:0}, function () {_this.over = true;        });                Then move left _this._setsquare (); }},/** * Gets the first node * @param element * @returns {*} */_g Etfirstelement:function (Element) {if (element.firstelementchild) {return element.firstelemen            Tchild;                } else {var ele = Element.firstchild;                while (Ele && ele.nodetype!== 1) {ele = ele.nextsibling;            } return ele; }},/** * Gets the last node * @param element * @returns {*} */_getlastelemen            T:function (Element) {if (element.lastelementchild) {return element.lastelementchild;                } else {var ele = Element.lastchild; while (Ele &&amP                Ele.nodetype!== 1) {ele = ele.previoussibling;            } return ele; }},/** * animation function * @param obj Motion Object * @param JSON changed properties * @param f            N callback function */_animateeffect:function (obj, JSON, fn) {var _this = this;            Clearinterval (Obj.timer);            Obj.timer = setinterval (function () {var flag = true;                        First assume that all properties have reached the target location for (var. k in JSON) {if (k = = "opacity") {//To determine the transparency condition       var leader = json[k] * 100;       Opacity change does not set gradient var target = json[k] * 100;                        Target position if ("opacity" in Obj.style) {obj.style[k] = leader/100;   } else {obj.style.filter = "alpha (opacity =" + target + ")";                Compatible with IE6}    } else if (k = = "ZIndex") {//judging hierarchy condition leader = parseint (obj, k)) | | 0;                        Level changes also do not set gradient target = Json[k];                    OBJ.STYLE[K] = target;                        } else {leader = parseint (GetStyle (obj, k)) | | 0;                        target = Json[k]; var step = target > leader? Math.ceil ((Target-leader)/Ten): Math.floor ((Target-leader)/10);                        Easing formula leader + = step;                    Obj.style[k] = leader + "px";                    if (leader! = target) {//As long as there is a property not reaching the target position flag = false;                     }} if (flag) {//Clears the timer clearinterval (Obj.timer) When all properties have reached the target location;                    if (FN) {//If there is a callback function executing the callback function fn ();        }}}, 15);    }    }; Support AMDModular if (typeof define!== "undefined" && typeof define = = = "function") {define ("Carousel", [],function () {        return Carousel;    });    }else {W.carousel = Carousel; }} (window));

The above is the implementation of JS, but only this is not enough, to match the specified style to use the line, the following is the specific HTML code and CSS style:

<! DOCTYPE html>

With the above two files, you can use the new instance to instantiate a carousel map to the page to specify the location, is not very convenient? But there are a lot of things to optimize, such as my package of this motion function is not very perfect, this Carousel diagram component is still a bit small bug, that is, in the left and right to switch the picture when there is sometimes a little white stripes, the main reason is estimated to be the problem of motion function.

After the use of the original package to give me the feeling is to consider a lot of compatibility issues, in the process of encapsulation good memory jquery Ah, the use of simple rough, do not consider compatibility issues. However, I have gained a lot by considering the compatibility problem, for example, the function of adding an event above addevents, the first way I did this:

/**     * Add Event     * @param target    to whom to add     * @param type      added event type     * @param handler   event handler    */ Addevent:function (target, type, handler) {        //ability to detect        if (target && target.addeventlistener) {            Return Target.addeventlistener (type, handler, false);        } else if (target && target.attachevent) {            return target.attachevent ("on" + type, handler);        } else {            return target["on" + type] = handler;        }    }

One problem here is that I make three judgments every time I register an event with an element on the page. Each time you register an event will be judged three times, so waste a lot of memory, considering this problem, so I have a little improvement on this event registration function, as follows:

/**     * Add Event     * @param target    to whom to add     * @param type      added event type     * @param handler   event handler    */ var addevents =  (function () {        //capability detect        if (Window.addeventlistener) {            return function (target, type, Handler) {                target.addeventlistener (type,handler,false);            };        } else if (window.attachevent) {            return function (target, type, handler) {                target.attachevent ("on" + type, handler);}}    ) ();

is to wrap the process of judgment in an immediate execution function, and when the page is loaded here it automatically depends on the browser type to determine which event registration method is supported by the current browser, and will then return an anonymous function assignment in the addevents variable. After each call to the function of the registration event, it is not necessary to re-judge, thereby solving the problem, saving memory.

There is a small detail here, that is, I set a default parameter is the rotation of the graph delay, when the user has passed this parameter is the use of user-transmitted parameters, or use the default parameters, when the configuration information opts attached to the constructor of this is also considered the default parameters. I first determine if the property in the incoming opts has the default parameter time property, if there is no default parameter in the OPTs time property, the default parameter, time is added to the OPTs, and the configuration information opts appended to the constructor's this, so that the default parameters are not modified. This guarantees the consistency of the default parameters, which are the same for each instantiation of the default parameters.

A simple small component, please expert guidance.

Native JS object-oriented idea encapsulates the Carousel diagram component

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.