UNPKG

metro4

Version:

The front-end framework for Build responsive, mobile-first projects on the web with the first front-end component library in Metro Style

610 lines (491 loc) 22.8 kB
var Streamer = { init: function( options, elem ) { this.options = $.extend( {}, this.options, options ); this.elem = elem; this.element = $(elem); this.data = null; this._setOptionsFromDOM(); this._create(); return this; }, options: { duration: METRO_ANIMATION_DURATION, defaultClosedIcon: "", defaultOpenIcon: "", changeUri: true, encodeLink: true, closed: false, chromeNotice: false, startFrom: null, slideToStart: true, startSlideSleep: 1000, source: null, data: null, eventClick: "select", selectGlobal: true, streamSelect: false, excludeSelectElement: null, excludeClickElement: null, excludeElement: null, excludeSelectClass: "", excludeClickClass: "", excludeClass: "", onStreamClick: Metro.noop, onStreamSelect: Metro.noop, onEventClick: Metro.noop, onEventSelect: Metro.noop, onStreamerCreate: Metro.noop }, _setOptionsFromDOM: function(){ var that = this, element = this.element, o = this.options; $.each(element.data(), function(key, value){ if (key in o) { try { o[key] = JSON.parse(value); } catch (e) { o[key] = value; } } }); }, _create: function(){ var that = this, element = this.element, o = this.options; element.addClass("streamer"); if (element.attr("id") === undefined) { element.attr("id", Utils.elementId("streamer")); } if (o.source === null && o.data === null) { return false; } $("<div>").addClass("streams").appendTo(element); $("<div>").addClass("events-area").appendTo(element); if (o.source !== null) { $.get(o.source, function(data){ that.data = data; that.build(); }); } else { this.data = o.data; this.build(); } this._createEvents(); if (o.chromeNotice === true && Utils.detectChrome() === true && Utils.isTouchDevice() === false) { $("<p>").addClass("text-small text-muted").html("*) In Chrome browser please press and hold Shift and turn the mouse wheel.").insertAfter(element); } }, build: function(){ var that = this, element = this.element, o = this.options, data = this.data; var streams = element.find(".streams").html(""); var events_area = element.find(".events-area").html(""); var timeline = $("<ul>").addClass("streamer-timeline").html("").appendTo(events_area); var streamer_events = $("<div>").addClass("streamer-events").appendTo(events_area); var event_group_main = $("<div>").addClass("event-group").appendTo(streamer_events); var StreamerIDS = Utils.getURIParameter(null, "StreamerIDS"); if (StreamerIDS !== null && o.encodeLink === true) { StreamerIDS = atob(StreamerIDS); } var StreamerIDS_i = StreamerIDS ? StreamerIDS.split("|")[0] : null; var StreamerIDS_a = StreamerIDS ? StreamerIDS.split("|")[1].split(",") : []; if (data.actions !== undefined) { var actions = $("<div>").addClass("streamer-actions").appendTo(streams); $.each(data.actions, function(){ var item = this; var button = $("<button>").addClass("streamer-action").addClass(item.cls).html(item.html); if (item.onclick !== undefined) button.on(Metro.events.click, function(){ Utils.exec(item.onclick, [element]); }); button.appendTo(actions); }); } // Create timeline timeline.html(""); if (data.timeline === undefined) { data.timeline = { start: "09:00", stop: "18:00", step: 20 } } var start = new Date(), stop = new Date(); var start_time_array = data.timeline.start ? data.timeline.start.split(":") : [9,0]; var stop_time_array = data.timeline.stop ? data.timeline.stop.split(":") : [18,0]; var step = data.timeline.step ? parseInt(data.timeline.step) * 60 : 1200; start.setHours(start_time_array[0]); start.setMinutes(start_time_array[1]); start.setSeconds(0); stop.setHours(stop_time_array[0]); stop.setMinutes(stop_time_array[1]); stop.setSeconds(0); for (var i = start.getTime()/1000; i <= stop.getTime()/1000; i += step) { var t = new Date(i * 1000); var h = t.getHours(), m = t.getMinutes(); var v = (h < 10 ? "0"+h : h) + ":" + (m < 10 ? "0"+m : m); var li = $("<li>").data("time", v).addClass("js-time-point-" + v.replace(":", "-")).html("<em>"+v+"</em>").appendTo(timeline); } // -- End timeline creator if (data.streams !== undefined) { $.each(data.streams, function(stream_index){ var stream_item = this; var stream = $("<div>").addClass("stream").addClass(this.cls).appendTo(streams); stream .addClass(stream_item.cls) .data("one", false) .data("data", stream_item.data); $("<div>").addClass("stream-title").html(stream_item.title).appendTo(stream); $("<div>").addClass("stream-secondary").html(stream_item.secondary).appendTo(stream); $(stream_item.icon).addClass("stream-icon").appendTo(stream); var bg = Utils.computedRgbToHex(Utils.getStyleOne(stream, "background-color")); var fg = Utils.computedRgbToHex(Utils.getStyleOne(stream, "color")); var stream_events = $("<div>").addClass("stream-events") .data("background-color", bg) .data("text-color", fg) .appendTo(event_group_main); if (stream_item.events !== undefined) { $.each(stream_item.events, function(event_index){ var event_item = this; var _icon; var sid = stream_index+":"+event_index; var custom_html = event_item.custom !== undefined ? event_item.custom : ""; var custom_html_open = event_item.custom_open !== undefined ? event_item.custom_open : ""; var custom_html_close = event_item.custom_close !== undefined ? event_item.custom_close : ""; var event = $("<div>") .data("origin", event_item) .data("sid", sid) .data("data", event_item.data) .data("time", event_item.time) .data("target", event_item.target) .addClass("stream-event") .addClass("size-"+event_item.size+"x") .addClass(event_item.cls) .appendTo(stream_events); var left = timeline.find(".js-time-point-"+this.time.replace(":", "-"))[0].offsetLeft - stream.outerWidth(); event.css({ position: "absolute", left: left }); var slide = $("<div>").addClass("stream-event-slide").appendTo(event); var slide_logo = $("<div>").addClass("slide-logo").appendTo(slide); var slide_data = $("<div>").addClass("slide-data").appendTo(slide); if (event_item.icon !== undefined) { if (Utils.isTag(event_item.icon)) { $(event_item.icon).addClass("icon").appendTo(slide_logo); } else { $("<img>").addClass("icon").attr("src", event_item.icon).appendTo(slide_logo); } } $("<span>").addClass("time").css({ backgroundColor: bg, color: fg }).html(event_item.time).appendTo(slide_logo); $("<div>").addClass("title").html(event_item.title).appendTo(slide_data); $("<div>").addClass("subtitle").html(event_item.subtitle).appendTo(slide_data); $("<div>").addClass("desc").html(event_item.desc).appendTo(slide_data); if (o.closed === false && (element.attr("id") === StreamerIDS_i && StreamerIDS_a.indexOf(sid) !== -1) || event_item.selected === true || parseInt(event_item.selected) === 1) { event.addClass("selected"); } if (o.closed === true || event_item.closed === true || parseInt(event_item.closed) === 1) { _icon = event_item.closedIcon !== undefined ? Utils.isTag(event_item.closedIcon) ? event_item.closedIcon : "<span>"+event_item.closedIcon+"</span>" : Utils.isTag(o.defaultClosedIcon) ? o.defaultClosedIcon : "<span>"+o.defaultClosedIcon+"</span>"; $(_icon).addClass("state-icon").addClass(event_item.clsClosedIcon).appendTo(slide); event .data("closed", true) .data("target", event_item.target); event.append(custom_html_open); } else { _icon = event_item.openIcon !== undefined ? Utils.isTag(event_item.openIcon) ? event_item.openIcon : "<span>"+event_item.openIcon+"</span>" : Utils.isTag(o.defaultOpenIcon) ? o.defaultOpenIcon : "<span>"+o.defaultOpenIcon+"</span>"; $(_icon).addClass("state-icon").addClass(event_item.clsOpenIcon).appendTo(slide); event .data("closed", false); event.append(custom_html_close); } event.append(custom_html); }); var last_child = stream_events.find(".stream-event:last-child"); if (last_child.length > 0) stream_events.outerWidth(last_child[0].offsetLeft + last_child.outerWidth()); } }); } if (data.global !== undefined) { $.each(['before', 'after'], function(){ var global_item = this; if (data.global[global_item] !== undefined) { $.each(data.global[global_item], function(){ var event_item = this; var group = $("<div>").addClass("event-group").addClass("size-"+event_item.size+"x"); var events = $("<div>").addClass("stream-events global-stream").appendTo(group); var event = $("<div>").addClass("stream-event").appendTo(events); event .addClass("global-event") .addClass(event_item.cls) .data("time", event_item.time) .data("origin", event_item) .data("data", event_item.data); $("<div>").addClass("event-title").html(event_item.title).appendTo(event); $("<div>").addClass("event-subtitle").html(event_item.subtitle).appendTo(event); $("<div>").addClass("event-html").html(event_item.html).appendTo(event); var left, t = timeline.find(".js-time-point-"+this.time.replace(":", "-")); if (t.length > 0) left = t[0].offsetLeft - streams.find(".stream").outerWidth(); group.css({ position: "absolute", left: left, height: "100%" }).appendTo(streamer_events); }); } }); } element.data("stream", -1); if (o.startFrom !== null && o.slideToStart === true) { setTimeout(function(){ that.slideTo(o.startFrom); }, o.startSlideSleep); } Utils.exec(o.onStreamerCreate, [element]); }, _createEvents: function(){ var that = this, element = this.element, o = this.options; element.on(Metro.events.click, ".stream-event", function(e){ var event = $(this); if (o.excludeClass !== "" && event.hasClass(o.excludeClass)) { return ; } if (o.excludeElement !== null && $(e.target).is(o.excludeElement)) { return ; } if (o.closed === false && event.data("closed") !== true && o.eventClick === 'select') { if (o.excludeSelectClass !== "" && event.hasClass(o.excludeSelectClass)) { } else { if (o.excludeSelectElement !== null && $(e.target).is(o.excludeSelectElement)) { } else { if (event.hasClass("global-event")) { if (o.selectGlobal === true) { event.toggleClass("selected"); } } else { event.toggleClass("selected"); } if (o.changeUri === true) { that._changeURI(); } Utils.exec(o.onEventSelect, [event, event.hasClass("selected")]); } } } else { if (o.excludeClickClass !== "" && event.hasClass(o.excludeClickClass)) { } else { if (o.excludeClickElement !== null && $(e.target).is(o.excludeClickElement)) { } else { Utils.exec(o.onEventClick, [event]); if (o.closed === true || event.data("closed") === true) { var target = event.data("target"); if (target) { window.location.href = target; } } } } } }); element.on(Metro.events.click, ".stream", function(e){ var stream = $(this); var index = stream.index(); if (o.streamSelect === false) { return; } console.log(index, element.data("stream")); if (element.data("stream") === index) { element.find(".stream-event").removeClass("disabled"); element.data("stream", -1); } else { element.data("stream", index); element.find(".stream-event").addClass("disabled"); that.enableStream(stream); Utils.exec(o.onStreamSelect, [stream]); } Utils.exec(o.onStreamClick, [stream]); }); if (Utils.isTouchDevice() !== true) { element.on(Metro.events.mousewheel, ".events-area", function(e) { var acrollable = $(this); if (e.deltaY === undefined || e.deltaFactor === undefined) { return ; } if (e.deltaFactor > 1) { var scroll = acrollable.scrollLeft() - ( e.deltaY * 30 ); acrollable.scrollLeft(scroll); e.preventDefault(); } }); } if (Utils.isTouchDevice() === true) { element.on(Metro.events.click, ".stream", function(){ var stream = $(this); stream.toggleClass("focused"); $.each(element.find(".stream"), function () { if ($(this).is(stream)) return ; $(this).removeClass("focused"); }) }) } }, _changeURI: function(){ var that = this, element = this.element, o = this.options, data = this.data; var link = this.getLink(); history.pushState({}, document.title, link); }, slideTo: function(time){ var that = this, element = this.element, o = this.options, data = this.data; var target; if (time === undefined) { target = $(element.find(".streamer-timeline li")[0]); } else { target = $(element.find(".streamer-timeline .js-time-point-" + time.replace(":", "-"))[0]); } element.find(".events-area").animate({ scrollLeft: target[0].offsetLeft - element.find(".streams .stream").outerWidth() }, o.duration); }, enableStream: function(stream){ var that = this, element = this.element, o = this.options, data = this.data; var index = stream.index()-1; stream.removeClass("disabled").data("streamDisabled", false); element.find(".stream-events").eq(index).find(".stream-event").removeClass("disabled"); }, disableStream: function(stream){ var that = this, element = this.element, o = this.options, data = this.data; var index = stream.index()-1; stream.addClass("disabled").data("streamDisabled", true); element.find(".stream-events").eq(index).find(".stream-event").addClass("disabled"); }, toggleStream: function(stream){ if (stream.data("streamDisabled") === true) { this.enableStream(stream); } else { this.disableStream(stream); } }, getLink: function(){ var that = this, element = this.element, o = this.options, data = this.data; var events = element.find(".stream-event"); var a = []; var link; var origin = window.location.href; $.each(events, function(){ var event = $(this); if (event.data("sid") === undefined || !event.hasClass("selected")) { return; } a.push(event.data("sid")); }); link = element.attr("id") + "|" + a.join(","); if (o.encodeLink === true) { link = btoa(link); } return Utils.updateURIParameter(origin, "StreamerIDS", link); }, getTimes: function(){ var that = this, element = this.element, o = this.options, data = this.data; var times = element.find(".streamer-timeline > li"); var result = []; $.each(times, function(){ result.push($(this).data("time")); }); return result; }, getEvents: function(event_type, include_global){ var that = this, element = this.element, o = this.options, data = this.data; var items, events = []; switch (event_type) { case "selected": items = element.find(".stream-event.selected"); break; case "non-selected": items = element.find(".stream-event:not(.selected)"); break; default: items = element.find(".stream-event"); } $.each(items, function(){ var item = $(this); var origin; if (include_global !== true && item.parent().hasClass("global-stream")) return ; origin = item.data("origin"); events.push(origin); }); return events; }, source: function(s){ if (s === undefined) { return this.options.source; } this.options.source = s; this.changeSource(); }, data: function(s){ if (s === undefined) { return this.options.source; } this.options.data = s; this.changeData(); }, getStreamerData: function(){ return this.data; }, toggleEvent: function(event){ var that = this, element = this.element, o = this.options, data = this.data; event = $(event); if (event.hasClass("global-event") && o.selectGlobal !== true) { return ; } if (event.hasClass("selected")) { this.selectEvent(event, false); } else { this.selectEvent(event, true); } }, selectEvent: function(event, state){ var that = this, element = this.element, o = this.options, data = this.data; if (state === undefined) { state = true; } event = $(event); if (event.hasClass("global-event") && o.selectGlobal !== true) { return ; } if (state === true) event.addClass("selected"); else event.removeClass("selected"); if (o.changeUri === true) { that._changeURI(); } Utils.exec(o.onEventSelect, [event, state]); }, changeSource: function(){ var that = this, element = this.element, o = this.options, data = this.data; var new_source = element.attr("data-source"); if (String(new_source).trim() === "") { return ; } o.source = new_source; $.get(o.source, function(data){ that.data = data; that.build(); }); element.trigger("sourcechanged"); }, changeData: function(){ var that = this, element = this.element, o = this.options, data = this.data; var new_data = element.attr("data-data"); if (String(new_data).trim() === "") { return ; } o.data = new_data; this.data = JSON.parse(o.data); this.build(); element.trigger("datachanged"); }, changeStreamSelectOption: function(){ var that = this, element = this.element, o = this.options, data = this.data; o.streamSelect = element.attr("data-stream-select").toLowerCase() === "true"; }, changeAttribute: function(attributeName){ switch (attributeName) { case 'data-source': this.changeSource(); break; case 'data-data': this.changeData(); break; case 'data-stream-select': this.changeStreamSelectOption(); break; } } }; Metro.plugin('streamer', Streamer);