PageSourceSearch

https://www.zoloft.com/-/media/Base-Themes/Components-Theme/Scripts/component-video-playlist.js

js zoloft.com collected 2026-09-24 20:04:42 UTC 11,665 bytes, 325 lines download raw bytes

1/* global mejs:false */
2/**
3 * Component Playlist
4 * @module Playlist
5 * @param  {jQuery} $ Instance of jQuery
6 * @return {Object} List of Playlist component methods
7 */
8XA.component.playlist = (function ($) {
9    /**
10     * This object stores all public api methods
11     * @type {Object.<Methods>}
12     * @memberOf module:Playlist
13     * */
14    var api = {};
15    /**
16     * This class is used by [Playlist]{@link module:Playlist} module
17     * @class Playlist
18     * @memberOf module:Playlist
19     * @param {jQuery} playlist Root DOM element of playlist component wrapped by jQuery
20     * @param {Object} properties Properties set in data attribute
21     */
22    function Playlist(playlist, properties) {
23        this.properties = properties;
24        this.playlist = playlist;
25        this.activeVideo = 0;
26        this.playlistItems = 0;
27    }
28    /**
29     * Creates new source element, sets up it with type & src. Created element
30     * append to Video container (take it from videoContainer parameter)
31     * @method
32     * @alias createNewSources
33     * @memberOf module:Playlist.Playlist
34     * @param {$OrderedList} source takes from properties.sources[itemIndex].src - 
35     * source of playlist element
36     * @param {$OrderedList} videoContainer container where source should be added
37     */
38    Playlist.prototype.createNewSources = function (source, videoContainer) {
39        var newSource;
40
41        var sourceBuilder = function (path) {
42            var newSource = $("<source>"),
43                type;
44
45            if (path.match(/\.(mp4)$/)) {
46                type = "video/mp4";
47            } else if (path.match(/\.(webm)$/)) {
48                type = "video/webm";
49            } else if (path.match(/\.(ogv)$/)) {
50                type = "video/ogg";
51            } else {
52                type = "video/youtube";
53            }
54
55            newSource.attr({
56                type: type,
57                src: path
58            });
59
60            return newSource;
61        };
62
63        if (source instanceof Array) {
64            for (var i = 0; i < source.length; i++) {
65                newSource = sourceBuilder(source[i]);
66                videoContainer.find("video").append(newSource);
67            }
68        } else {
69            newSource = sourceBuilder(source);
70            videoContainer.find("video").append(newSource);
71        }
72    };
73    /**
74     * Replaces source of each video element under play list component.
75     * After replacing it re-initializes video component by calling 
76     * [XA.component.video.initVideoFromPlaylist]{@link module:Video.initVideoFromPlaylist}
77     * @name replaceSource
78     * @function
79     * @param {number} itemIndex position of active video in video list
80     * @param {boolean} loadFromEvent
81     * @memberOf module:Playlist.Playlist
82     */
83
84    Playlist.prototype.replaceSource = function (itemIndex, loadFromEvent) {
85        var inst = this,
86            videoContainer,
87            videoClone,
88            newSrc = inst.properties.sources[itemIndex].src,
89            sources,
90            videoId,
91            videoContainerHeight = 0;
92
93        $(inst.properties.playlistId).each(function () {
94            videoContainer = $(this);
95            videoId = inst.properties.playlistId;
96
97            if (videoContainer.is(videoId) && newSrc.length) {
98                videoContainer.addClass("show");
99
100                sources = videoContainer.find("source");
101                sources.remove();
102                inst.createNewSources(newSrc, videoContainer);
103                videoContainer
104                    .find("video")
105                    .attr({
106                        src: ""
107                    })
108                    .show();
109
110                var autoplayVideo = false;
111                if (loadFromEvent) {
112                    if (inst.properties.autoPlaySelected) {
113                        autoplayVideo = true;
114                    }
115                } else {
116                    if (inst.properties.autoPlay) {
117                        autoplayVideo = true;
118                    }
119                }
120
121                if (autoplayVideo) {
122                    videoContainer.find("video").attr({
123                        autoplay: ""
124                    });
125                }
126
127                videoClone = videoContainer.find("video").clone();
128                videoContainerHeight = videoContainer.height();
129                videoContainer.css({
130                    height: videoContainerHeight
131                });
132
133                var id = videoContainer.find(".mejs-container").attr("id");
134                if (id) {
135                    $("#" + id).remove();
136                    delete mejs.players[id];
137                    videoContainer
138                        .find(".component-content")
139                        .append(videoClone);
140                }
141
142                XA.component.video.initVideoFromPlaylist(
143                    videoContainer,
144                    inst.playlist
145                );
146                videoContainer.css({
147                    height: "auto"
148                });
149            }
150        });
151    };
152
153    /**
154     * Initializes videos under component. On call and on
155     * [change-video]{@link module:Playlist.Playlist#change-video} event
156     * calls [replaceSource]{@link module:Playlist.Playlist.replaceSource}
157     * @name loadPlaylistVideo
158     * @function
159     * @listeners module:Playlist.Playlist#change-video
160     * @memberOf module:Playlist.Playlist
161     */
162
163    Playlist.prototype.loadPlaylistVideo = function () {
164        var inst = this,
165            playlistItems = $(inst.playlist).find(".playlist-item"),
166            activeListItem;
167
168        inst.playlistItems = playlistItems.length;
169        var loadVideoFromPlaylist = function (loadFromEvent) {
170            inst.replaceSource(inst.activeVideo, loadFromEvent);
171            activeListItem = playlistItems.eq(inst.activeVideo);
172            activeListItem.addClass("active");
173            activeListItem.siblings().removeClass("active");
174        };
175
176        loadVideoFromPlaylist();
177        $(inst.playlist).on("change-video", function (event, properties) {
178            var loadNewVideo = false;
179            
180            if (properties) {
181                if (properties.hasOwnProperty("back")) {
182                    inst.activeVideo--;
183                    if (inst.activeVideo < 0) {
184                        inst.activeVideo = 0;
185                    } else {
186                        loadNewVideo = true;
187                    }
188                } else {
189                    inst.activeVideo++;
190                    if (inst.activeVideo === inst.playlistItems) {
191                        if (inst.properties.repeatAfterAll) {
192                            inst.activeVideo = 0;
193                            loadNewVideo = true;
194                        } else {
195                            inst.activeVideo = inst.playlistItems - 1;
196                        }
197                    } else {
198                        loadNewVideo = true;
199                    }
200                }
201            } else {
202                if (inst.properties.playNext) {
203                    if (inst.activeVideo + 1 <= inst.playlistItems) {
204                        inst.activeVideo++;
205
206                        if (inst.activeVideo === inst.playlistItems) {
207                            inst.activeVideo = 0;
208
209                            if (inst.properties.repeatAfterAll) {
210                                loadNewVideo = true;
211                            }
212                        } else {
213                            inst.actiVideo--;
214                            loadNewVideo = true;
215                        }
216                    }
217                }
218            }
219
220            if (loadNewVideo) {
221                loadVideoFromPlaylist(true);
222            }
223        });
224    };
225    /**
226     * Attaches events to playlist-section and navigation items
227     * @name attachEvents
228     * @function
229     * @fires module:Playlist.Playlist#change-video
230     * @memberOf module:Playlist.Playlist
231     */
232    Playlist.prototype.attachEvents = function () {
233        var inst = this,
234            link = $(inst.playlist).find(".playlist-section"),
235            navItems = $(inst.playlist).find(".playlist-nav a"),
236            playlistItem;
237        link.on("click", function (event) {
238            event.preventDefault();
239            if (!inst.locked) {
240                inst.locked = true;
241                playlistItem = $(this).parents(".playlist-item");
242                var itemIndex = playlistItem.index();
243
244                if (itemIndex !== inst.activeVideo) {
245                    playlistItem.addClass("active");
246                    playlistItem.siblings().removeClass("active");
247                    inst.replaceSource(itemIndex, true);
248                    inst.activeVideo = itemIndex;
249                }
250                //Change video source not more often
251                //than once per second
252                setTimeout(function(){
253                    inst.locked = false;
254                },1000);
255            }
256
257        });
258
259        navItems.on("click", function (event) {
260            event.preventDefault();
261            var properties = {};
262
263            if (
264                $(this)
265                    .parent()
266                    .hasClass("playlist-prev")
267            ) {
268                properties.back = true;
269            }
270            /**
271             * Change video event fires when user clicks
272             * a ".playlist-nav a" element.
273             *
274             * @event module:Playlist.Playlist#change-video
275             * @type {object}
276             * @property {Object} properties - Indicates whether playlist has back button
277             */
278            $(inst.playlist).trigger("change-video", properties);
279        });
280    };
281    /**
282     * For each playlist component creates new instance of
283     * ["Playlist"]{@link  module:Playlist.Playlist} and calls
284     * ["loadPlaylistVideo"]{@link  module:Playlist.Playlist.loadPlaylistVideo},
285     * ["attachEvents"]{@link  module:Playlist.Playlist.attachEvents}
286     * methods
287     * @memberOf module:Playlist
288     * @method
289     * @param {jQuery} component Root DOM element of playlist component wrapped by jQuery
290     * @param {Object} prop Properties set in data attribute
291     *  of playlist component
292     * @alias module:Playlist.initInstance
293     */
294    api.initInstance = function (component, prop) {
295        var playlist;
296        $(prop.playlistId).addClass("initialized"); //prevents video init in component-video.js
297        if (prop.sources.length) {
298            playlist = new Playlist(component, prop);
299            playlist.loadPlaylistVideo();
300            playlist.attachEvents();
301        }
302    };
303    /**
304     * Finds all not initialized yet
305     * Playlist components and in a loop for each of them
306     * run ["initInstance"]{@link module:Playlist.initInstance}
307     * method.
308     * @memberOf module:Playlist
309     * @alias module:Playlist.init
310     */
311    api.init = function () {
312        var playlists = $(".playlist.component:not(.initialized)"),
313            properties;
314
315        playlists.each(function () {
316            properties = $(this).data("properties");
317            api.initInstance(this, properties);
318            $(this).addClass("initialized");
319        });
320    };
321
322    return api;
323})(jQuery, document);
324
325XA.register("playlist", XA.component.playlist);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.