diff --git a/buildout.cfg b/buildout.cfg
index ff78820..b1e81b3 100644
--- a/buildout.cfg
+++ b/buildout.cfg
@@ -12,6 +12,11 @@ parts +=
i18ndude
omelette
rebuild_i18n-sh
+ webpack
+ webpack_env
+ npm_watch
+ npm_dev
+ npm_build
[code-analysis]
recipe = plone.recipe.codeanalysis[recommended]
@@ -32,6 +37,57 @@ eggs = i18ndude
recipe = collective.recipe.omelette
eggs = ${instance:eggs}
+[webpack]
+recipe = gp.recipe.node
+version = 6.6.0
+npms = npm yarn webpack@2
+scripts = npm yarn webpack
+
+[webpack_env]
+recipe = collective.recipe.template
+input = inline:
+ #!/bin/sh
+ export PATH=${buildout:bin-directory}:$PATH
+ cd webpack
+ yarn
+ exec $SHELL
+output = ${buildout:bin-directory}/webpack_env
+mode = 755
+
+[npm_watch]
+recipe = collective.recipe.template
+input = inline:
+ #!/bin/sh
+ PATH=${buildout:bin-directory}:$PATH
+ cd webpack
+ yarn
+ npm run watch
+output = ${buildout:bin-directory}/npm_watch
+mode = 755
+
+[npm_dev]
+recipe = collective.recipe.template
+input = inline:
+ #!/bin/sh
+ PATH=${buildout:bin-directory}:$PATH
+ cd webpack
+ yarn
+ npm run dev
+output = ${buildout:bin-directory}/npm_dev
+mode = 755
+
+[npm_build]
+recipe = collective.recipe.template
+input = inline:
+ #!/bin/sh
+ PATH=${buildout:bin-directory}:$PATH
+ cd webpack
+ yarn
+ npm run build
+output = ${buildout:bin-directory}/npm_build
+mode = 755
+
[versions]
# use latest version of coverage
coverage =
+
diff --git a/src/collective/newsticker/browser/static/controls.png b/src/collective/newsticker/browser/static/controls.png
index 08535be..fd65904 100644
Binary files a/src/collective/newsticker/browser/static/controls.png and b/src/collective/newsticker/browser/static/controls.png differ
diff --git a/src/collective/newsticker/browser/static/jquery.ticker.js b/src/collective/newsticker/browser/static/jquery.ticker.js
deleted file mode 100644
index 96799e8..0000000
--- a/src/collective/newsticker/browser/static/jquery.ticker.js
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- jQuery News Ticker is free software: you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation, version 2 of the License.
-
- jQuery News Ticker is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with jQuery News Ticker. If not, see .
-*/
-(function($){
- $.fn.ticker = function(options) {
- // Extend our default options with those provided.
- // Note that the first arg to extend is an empty object -
- // this is to keep from overriding our "defaults" object.
- var opts = $.extend({}, $.fn.ticker.defaults, options);
-
- // check that the passed element is actually in the DOM
- if ($(this).length == 0) {
- if (window.console && window.console.log) {
- window.console.log('Element does not exist in DOM!');
- }
- else {
- alert('Element does not exist in DOM!');
- }
- return false;
- }
-
- /* Get the id of the UL to get our news content from */
- var newsID = '#' + $(this).attr('id');
-
- /* Get the tag type - we will check this later to makde sure it is a UL tag */
- var tagType = $(this).get(0).tagName;
-
- return this.each(function() {
- // get a unique id for this ticker
- var uniqID = getUniqID();
-
- /* Internal vars */
- var settings = {
- position: 0,
- time: 0,
- distance: 0,
- newsArr: {},
- play: true,
- paused: false,
- contentLoaded: false,
- dom: {
- contentID: '#ticker-content-' + uniqID,
- titleID: '#ticker-title-' + uniqID,
- titleElem: '#ticker-title-' + uniqID + ' SPAN',
- tickerID : '#ticker-' + uniqID,
- wrapperID: '#ticker-wrapper-' + uniqID,
- revealID: '#ticker-swipe-' + uniqID,
- revealElem: '#ticker-swipe-' + uniqID + ' SPAN',
- controlsID: '#ticker-controls-' + uniqID,
- prevID: '#prev-' + uniqID,
- nextID: '#next-' + uniqID,
- playPauseID: '#play-pause-' + uniqID
- }
- };
-
- // if we are not using a UL, display an error message and stop any further execution
- if (tagType != 'UL' && tagType != 'OL' && opts.htmlFeed === true) {
- debugError('Cannot use <' + tagType.toLowerCase() + '> type of element for this plugin - must of type
or ');
- return false;
- }
-
- // set the ticker direction
- opts.direction == 'rtl' ? opts.direction = 'right' : opts.direction = 'left';
-
- // lets go...
- initialisePage();
- /* Function to get the size of an Object*/
- function countSize(obj) {
- var size = 0, key;
- for (key in obj) {
- if (obj.hasOwnProperty(key)) size++;
- }
- return size;
- };
-
- function getUniqID() {
- var newDate = new Date;
- return newDate.getTime();
- }
-
- /* Function for handling debug and error messages */
- function debugError(obj) {
- if (opts.debugMode) {
- if (window.console && window.console.log) {
- window.console.log(obj);
- }
- else {
- alert(obj);
- }
- }
- }
-
- /* Function to setup the page */
- function initialisePage() {
- // process the content for this ticker
- processContent();
-
- // add our HTML structure for the ticker to the DOM
- $(newsID).wrap('');
-
- // remove any current content inside this ticker
- $(settings.dom.wrapperID).children().remove();
-
- $(settings.dom.wrapperID).append('
');
- $(settings.dom.wrapperID).removeClass('no-js').addClass('ticker-wrapper has-js ' + opts.direction);
- // hide the ticker
- $(settings.dom.tickerElem + ',' + settings.dom.contentID).hide();
- // add the controls to the DOM if required
- if (opts.controls) {
- // add related events - set functions to run on given event
- $(settings.dom.controlsID).live('click mouseover mousedown mouseout mouseup', function (e) {
- var button = e.target.id;
- if (e.type == 'click') {
- switch (button) {
- case settings.dom.prevID.replace('#', ''):
- // show previous item
- settings.paused = true;
- $(settings.dom.playPauseID).addClass('paused');
- manualChangeContent('prev');
- break;
- case settings.dom.nextID.replace('#', ''):
- // show next item
- settings.paused = true;
- $(settings.dom.playPauseID).addClass('paused');
- manualChangeContent('next');
- break;
- case settings.dom.playPauseID.replace('#', ''):
- // play or pause the ticker
- if (settings.play == true) {
- settings.paused = true;
- $(settings.dom.playPauseID).addClass('paused');
- pauseTicker();
- }
- else {
- settings.paused = false;
- $(settings.dom.playPauseID).removeClass('paused');
- restartTicker();
- }
- break;
- }
- }
- else if (e.type == 'mouseover' && $('#' + button).hasClass('controls')) {
- $('#' + button).addClass('over');
- }
- else if (e.type == 'mousedown' && $('#' + button).hasClass('controls')) {
- $('#' + button).addClass('down');
- }
- else if (e.type == 'mouseup' && $('#' + button).hasClass('controls')) {
- $('#' + button).removeClass('down');
- }
- else if (e.type == 'mouseout' && $('#' + button).hasClass('controls')) {
- $('#' + button).removeClass('over');
- }
- });
- // add controls HTML to DOM
- $(settings.dom.wrapperID).append('
');
- }
- if (opts.displayType != 'fade') {
- // add mouse over on the content
- $(settings.dom.contentID).mouseover(function () {
- if (settings.paused == false) {
- pauseTicker();
- }
- }).mouseout(function () {
- if (settings.paused == false) {
- restartTicker();
- }
- });
- }
- // we may have to wait for the ajax call to finish here
- if (!opts.ajaxFeed) {
- setupContentAndTriggerDisplay();
- }
- }
-
- /* Start to process the content for this ticker */
- function processContent() {
- // check to see if we need to load content
- if (settings.contentLoaded == false) {
- // construct content
- if (opts.ajaxFeed) {
- if (opts.feedType == 'xml') {
- $.ajax({
- url: opts.feedUrl,
- cache: false,
- dataType: opts.feedType,
- async: true,
- success: function(data){
- count = 0;
- // get the 'root' node
- for (var a = 0; a < data.childNodes.length; a++) {
- if (data.childNodes[a].nodeName == 'rss') {
- xmlContent = data.childNodes[a];
- }
- }
- // find the channel node
- for (var i = 0; i < xmlContent.childNodes.length; i++) {
- if (xmlContent.childNodes[i].nodeName == 'channel') {
- xmlChannel = xmlContent.childNodes[i];
- }
- }
- // for each item create a link and add the article title as the link text
- for (var x = 0; x < xmlChannel.childNodes.length; x++) {
- if (xmlChannel.childNodes[x].nodeName == 'item') {
- xmlItems = xmlChannel.childNodes[x];
- var title, link = false;
- for (var y = 0; y < xmlItems.childNodes.length; y++) {
- if (xmlItems.childNodes[y].nodeName == 'title') {
- title = xmlItems.childNodes[y].lastChild.nodeValue;
- }
- else if (xmlItems.childNodes[y].nodeName == 'link') {
- link = xmlItems.childNodes[y].lastChild.nodeValue;
- }
- if ((title !== false && title != '') && link !== false) {
- settings.newsArr['item-' + count] = { type: opts.titleText, content: '' + title + '' }; count++; title = false; link = false;
- }
- }
- }
- }
- // quick check here to see if we actually have any content - log error if not
- if (countSize(settings.newsArr < 1)) {
- debugError('Couldn\'t find any content from the XML feed for the ticker to use!');
- return false;
- }
- settings.contentLoaded = true;
- setupContentAndTriggerDisplay();
- }
- });
- }
- else {
- debugError('Code Me!');
- }
- }
- else if (opts.htmlFeed) {
- if($(newsID + ' LI').length > 0) {
- $(newsID + ' LI').each(function (i) {
- // maybe this could be one whole object and not an array of objects?
- settings.newsArr['item-' + i] = { type: opts.titleText, content: $(this).html()};
- });
- }
- else {
- debugError('Couldn\'t find HTML any content for the ticker to use!');
- return false;
- }
- }
- else {
- debugError('The ticker is set to not use any types of content! Check the settings for the ticker.');
- return false;
- }
- }
- }
-
- function setupContentAndTriggerDisplay() {
-
- settings.contentLoaded = true;
-
- // update the ticker content with the correct item
- // insert news content into DOM
- $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
- $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
-
- // set the next content item to be used - loop round if we are at the end of the content
- if (settings.position == (countSize(settings.newsArr) -1)) {
- settings.position = 0;
- }
- else {
- settings.position++;
- }
-
- // get the values of content and set the time of the reveal (so all reveals have the same speed regardless of content size)
- distance = $(settings.dom.contentID).width();
- time = distance / opts.speed;
-
- // start the ticker animation
- revealContent();
- }
-
- // slide back cover or fade in content
- function revealContent() {
- $(settings.dom.contentID).css('opacity', '1');
- if(settings.play) {
- // get the width of the title element to offset the content and reveal
- var offset = $(settings.dom.titleID).width() + 20;
-
- $(settings.dom.revealID).css(opts.direction, offset + 'px');
- // show the reveal element and start the animation
- if (opts.displayType == 'fade') {
- // fade in effect ticker
- $(settings.dom.revealID).hide(0, function () {
- $(settings.dom.contentID).css(opts.direction, offset + 'px').fadeIn(opts.fadeInSpeed, postReveal);
- });
- }
- else if (opts.displayType == 'scroll') {
- // to code
- }
- else {
- // default bbc scroll effect
- $(settings.dom.revealElem).show(0, function () {
- $(settings.dom.contentID).css(opts.direction, offset + 'px').show();
- // set our animation direction
- animationAction = opts.direction == 'right' ? { marginRight: distance + 'px'} : { marginLeft: distance + 'px' };
- $(settings.dom.revealID).css('margin-' + opts.direction, '0px').delay(20).animate(animationAction, time, 'linear', postReveal);
- });
- }
- }
- else {
- return false;
- }
- };
-
- // here we hide the current content and reset the ticker elements to a default state ready for the next ticker item
- function postReveal() {
- if(settings.play) {
- // we have to separately fade the content out here to get around an IE bug - needs further investigation
- $(settings.dom.contentID).delay(opts.pauseOnItems).fadeOut(opts.fadeOutSpeed);
- // deal with the rest of the content, prepare the DOM and trigger the next ticker
- if (opts.displayType == 'fade') {
- $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {
- $(settings.dom.wrapperID)
- .find(settings.dom.revealElem + ',' + settings.dom.contentID)
- .hide()
- .end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
- .show()
- .end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
- .removeAttr('style');
- setupContentAndTriggerDisplay();
- });
- }
- else {
- $(settings.dom.revealID).hide(0, function () {
- $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {
- $(settings.dom.wrapperID)
- .find(settings.dom.revealElem + ',' + settings.dom.contentID)
- .hide()
- .end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
- .show()
- .end().find(settings.dom.tickerID + ',' + settings.dom.revealID)
- .removeAttr('style');
- setupContentAndTriggerDisplay();
- });
- });
- }
- }
- else {
- $(settings.dom.revealElem).hide();
- }
- }
-
- // pause ticker
- function pauseTicker() {
- settings.play = false;
- // stop animation and show content - must pass "true, true" to the stop function, or we can get some funky behaviour
- $(settings.dom.tickerID + ',' + settings.dom.revealID + ',' + settings.dom.titleID + ',' + settings.dom.titleElem + ',' + settings.dom.revealElem + ',' + settings.dom.contentID).stop(true, true);
- $(settings.dom.revealID + ',' + settings.dom.revealElem).hide();
- $(settings.dom.wrapperID)
- .find(settings.dom.titleID + ',' + settings.dom.titleElem).show()
- .end().find(settings.dom.contentID).show();
- }
-
- // play ticker
- function restartTicker() {
- settings.play = true;
- settings.paused = false;
- // start the ticker again
- postReveal();
- }
-
- // change the content on user input
- function manualChangeContent(direction) {
- pauseTicker();
- switch (direction) {
- case 'prev':
- if (settings.position == 0) {
- settings.position = countSize(settings.newsArr) -2;
- }
- else if (settings.position == 1) {
- settings.position = countSize(settings.newsArr) -1;
- }
- else {
- settings.position = settings.position - 2;
- }
- $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
- $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
- break;
- case 'next':
- $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);
- $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);
- break;
- }
- // set the next content item to be used - loop round if we are at the end of the content
- if (settings.position == (countSize(settings.newsArr) -1)) {
- settings.position = 0;
- }
- else {
- settings.position++;
- }
- }
- });
- };
-
- // plugin defaults - added as a property on our plugin function
- $.fn.ticker.defaults = {
- speed: 0.10,
- ajaxFeed: false,
- feedUrl: '',
- feedType: 'xml',
- displayType: 'reveal',
- htmlFeed: true,
- debugMode: true,
- controls: true,
- titleText: 'Latest',
- direction: 'ltr',
- pauseOnItems: 3000,
- fadeInSpeed: 600,
- fadeOutSpeed: 300
- };
-})(jQuery);
\ No newline at end of file
diff --git a/src/collective/newsticker/browser/static/newsticker.css b/src/collective/newsticker/browser/static/newsticker.css
new file mode 100644
index 0000000..95108d0
--- /dev/null
+++ b/src/collective/newsticker/browser/static/newsticker.css
@@ -0,0 +1,2 @@
+.ticker-wrapper.has-js{font-size:.75em;width:780px;height:32px;margin:20px 0;padding:0 20px;border-radius:15px}.ticker,.ticker-wrapper.has-js{display:block;background-color:#f8f0db}.ticker{position:relative;overflow:hidden;width:710px;height:23px}.ticker-title{text-transform:uppercase;color:#900}.ticker-content,.ticker-title{font-weight:700;padding-top:9px;background-color:#f8f0db}.ticker-content{line-height:1.2em;position:absolute;overflow:hidden;margin:0;white-space:nowrap;color:#1f527b}.ticker-content a{text-decoration:none;color:#1f527b}.ticker-content a:hover{text-decoration:underline;color:#0d3059}.ticker-swipe{position:absolute;top:0;width:800px;height:23px;padding-top:9px}.ticker-swipe,.ticker-swipe span{display:block;background-color:#f8f0db}.ticker-swipe span{width:7px;height:12px;margin-left:1px;border-bottom:1px solid #1f527b}.ticker-controls{float:left;padding:8px 0 0;list-style-type:none}.ticker-controls li{display:block;float:left;width:16px;height:16px;margin-left:5px;padding:0;cursor:pointer}.ticker-controls li.jnt-play-pause{background-image:url(++resource++collective.newsticker/controls.png);background-position:32px 16px}.ticker-controls li.jnt-play-pause.over{background-position:32px 32px}.ticker-controls li.jnt-play-pause.down{background-position:32px 0}.ticker-controls li.jnt-play-pause.paused{background-image:url(++resource++collective.newsticker/controls.png);background-position:48px 16px}.ticker-controls li.jnt-play-pause.paused.over{background-position:48px 32px}.ticker-controls li.jnt-play-pause.paused.down{background-position:48px 0}.ticker-controls li.jnt-prev{background-image:url(++resource++collective.newsticker/controls.png);background-position:0 16px}.ticker-controls li.jnt-prev.over{background-position:0 32px}.ticker-controls li.jnt-prev.down{background-position:0 0}.ticker-controls li.jnt-next{background-image:url(++resource++collective.newsticker/controls.png);background-position:16px 16px}.ticker-controls li.jnt-next.over{background-position:16px 32px}.ticker-controls li.jnt-next.down{background-position:16px 0}.js-hidden{display:none}.no-js-news{padding:10px 0 0 45px;color:#f8f0db}.left .ticker-controls{padding-left:6px}.left .ticker,.left .ticker-content,.left .ticker-controls,.left .ticker-title{float:left}.right .ticker-controls{padding-right:6px}.right .ticker,.right .ticker-content,.right .ticker-controls,.right .ticker-title{float:right}
+/*# sourceMappingURL=newsticker.css.map*/
\ No newline at end of file
diff --git a/src/collective/newsticker/browser/static/newsticker.css.map b/src/collective/newsticker/browser/static/newsticker.css.map
new file mode 100644
index 0000000..b8f6691
--- /dev/null
+++ b/src/collective/newsticker/browser/static/newsticker.css.map
@@ -0,0 +1 @@
+{"version":3,"sources":[],"names":[],"mappings":"","file":"newsticker.css","sourceRoot":""}
\ No newline at end of file
diff --git a/src/collective/newsticker/browser/static/newsticker.js b/src/collective/newsticker/browser/static/newsticker.js
new file mode 100644
index 0000000..880b2a3
--- /dev/null
+++ b/src/collective/newsticker/browser/static/newsticker.js
@@ -0,0 +1,2 @@
+!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports["collective.newsticker"]=t():e["collective.newsticker"]=t()}(this,function(){return function(e){function t(n){if(o[n])return o[n].exports;var i=o[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,t),i.l=!0,i.exports}var o={};return t.m=e,t.c=o,t.i=function(e){return e},t.d=function(e,o,n){t.o(e,o)||Object.defineProperty(e,o,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var o=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(o,"a",o),o},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="++resource++collective.newsticker/",t(t.s=2)}([function(e,t){},function(e,t,o){e.exports=o.p+"newsticker_icon.png"},function(e,t,o){"use strict";o(0),o(1),$.fn.ticker=function(e){var t=$.extend({},$.fn.ticker.defaults,e);if(0==$(this).length)return window.console&&window.console.log?window.console.log("Element does not exist in DOM!"):alert("Element does not exist in DOM!"),!1;var o="#"+$(this).attr("id"),n=$(this).get(0).tagName;return this.each(function(){function e(e){var t=0,o=void 0;for(o in e)e.hasOwnProperty(o)&&t++;return t}function i(){var e=new Date;return e.getTime()}function d(e){t.debugMode&&(window.console&&window.console.log?window.console.log(e):alert(e))}function r(){s(),$(o).wrap(''),$(h.dom.wrapperID).children().remove(),$(h.dom.wrapperID).append('
')),"fade"!=t.displayType&&$(h.dom.contentID).mouseover(function(){0==h.paused&&p()}).mouseout(function(){0==h.paused&&m()}),t.ajaxFeed||l()}function s(){if(0==h.contentLoaded)if(t.ajaxFeed)"xml"==t.feedType?$.ajax({url:t.feedUrl,cache:!1,dataType:t.feedType,async:!0,success:function(o){count=0;for(var n=0;n'+s+""},count++,s=!1,a=!1)}return e(h.newsArr<1)?(d("Couldn't find any content from the XML feed for the ticker to use!"),!1):(h.contentLoaded=!0,void l())}}):d("Code Me!");else{if(!t.htmlFeed)return d("The ticker is set to not use any types of content! Check the settings for the ticker."),!1;if(!($(o+" LI").length>0))return d("Couldn't find HTML any content for the ticker to use!"),!1;$(o+" LI").each(function(e){h.newsArr["item-"+e]={type:t.titleText,content:$(this).html()}})}}function l(){h.contentLoaded=!0,$(h.dom.titleElem).html(h.newsArr["item-"+h.position].type),$(h.dom.contentID).html(h.newsArr["item-"+h.position].content),h.position==e(h.newsArr)-1?h.position=0:h.position++,a()}function a(){var e=$(h.dom.contentID).width(),o=e/t.speed;if($(h.dom.contentID).css("opacity","1"),!h.play)return!1;var n=$(h.dom.titleID).width()+20;$(h.dom.revealID).css(t.direction,n+"px"),"fade"==t.displayType?$(h.dom.revealID).hide(0,function(){$(h.dom.contentID).css(t.direction,n+"px").fadeIn(t.fadeInSpeed,c)}):"scroll"==t.displayType||$(h.dom.revealElem).show(0,function(){$(h.dom.contentID).css(t.direction,n+"px").show();var i="right"==t.direction?{marginRight:e+"px"}:{marginLeft:e+"px"};$(h.dom.revealID).css("margin-"+t.direction,"0px").delay(20).animate(i,o,"linear",c)})}function c(){h.play?($(h.dom.contentID).delay(t.pauseOnItems).fadeOut(t.fadeOutSpeed),"fade"==t.displayType?$(h.dom.contentID).fadeOut(t.fadeOutSpeed,function(){$(h.dom.wrapperID).find(h.dom.revealElem+","+h.dom.contentID).hide().end().find(h.dom.tickerID+","+h.dom.revealID).show().end().find(h.dom.tickerID+","+h.dom.revealID).removeAttr("style"),l()}):$(h.dom.revealID).hide(0,function(){$(h.dom.contentID).fadeOut(t.fadeOutSpeed,function(){$(h.dom.wrapperID).find(h.dom.revealElem+","+h.dom.contentID).hide().end().find(h.dom.tickerID+","+h.dom.revealID).show().end().find(h.dom.tickerID+","+h.dom.revealID).removeAttr("style"),l()})})):$(h.dom.revealElem).hide()}function p(){h.play=!1,$(h.dom.tickerID+","+h.dom.revealID+","+h.dom.titleID+","+h.dom.titleElem+","+h.dom.revealElem+","+h.dom.contentID).stop(!0,!0),$(h.dom.revealID+","+h.dom.revealElem).hide(),$(h.dom.wrapperID).find(h.dom.titleID+","+h.dom.titleElem).show().end().find(h.dom.contentID).show()}function m(){h.play=!0,h.paused=!1,c()}function u(t){switch(p(),t){case"prev":0==h.position?h.position=e(h.newsArr)-2:1==h.position?h.position=e(h.newsArr)-1:h.position=h.position-2,$(h.dom.titleElem).html(h.newsArr["item-"+h.position].type),$(h.dom.contentID).html(h.newsArr["item-"+h.position].content);break;case"next":$(h.dom.titleElem).html(h.newsArr["item-"+h.position].type),$(h.dom.contentID).html(h.newsArr["item-"+h.position].content)}h.position==e(h.newsArr)-1?h.position=0:h.position++}var f=i(),h={position:0,time:0,distance:0,newsArr:{},play:!0,paused:!1,contentLoaded:!1,dom:{contentID:"#ticker-content-"+f,titleID:"#ticker-title-"+f,titleElem:"#ticker-title-"+f+" SPAN",tickerID:"#ticker-"+f,wrapperID:"#ticker-wrapper-"+f,revealID:"#ticker-swipe-"+f,revealElem:"#ticker-swipe-"+f+" SPAN",controlsID:"#ticker-controls-"+f,prevID:"#prev-"+f,nextID:"#next-"+f,playPauseID:"#play-pause-"+f}};return"UL"!=n&&"OL"!=n&&t.htmlFeed===!0?(d("Cannot use <"+n.toLowerCase()+"> type of element for this plugin - must of type
or "),!1):("rtl"==t.direction?t.direction="right":t.direction="left",void r())})},$.fn.ticker.defaults={speed:.1,ajaxFeed:!1,feedUrl:"",feedType:"xml",displayType:"reveal",htmlFeed:!0,debugMode:!0,controls:!0,titleText:"Latest",direction:"ltr",pauseOnItems:3e3,fadeInSpeed:600,fadeOutSpeed:300}}])});
+//# sourceMappingURL=newsticker.js.map
\ No newline at end of file
diff --git a/src/collective/newsticker/browser/static/newsticker.js.map b/src/collective/newsticker/browser/static/newsticker.js.map
new file mode 100644
index 0000000..227587c
--- /dev/null
+++ b/src/collective/newsticker/browser/static/newsticker.js.map
@@ -0,0 +1 @@
+{"version":3,"sources":["webpack:///webpack/universalModuleDefinition","webpack:///newsticker.js","webpack:///webpack/bootstrap b1c492b02d9744a9b357","webpack:///./app/newsticker_icon.png","webpack:///./app/newsticker.js"],"names":["root","factory","exports","module","define","amd","this","modules","__webpack_require__","moduleId","installedModules","i","l","call","m","c","value","d","name","getter","o","Object","defineProperty","configurable","enumerable","get","n","__esModule","object","property","prototype","hasOwnProperty","p","s","$","fn","ticker","options","opts","extend","defaults","length","window","console","log","alert","newsID","attr","tagType","tagName","each","countSize","obj","size","key","getUniqID","newDate","Date","getTime","debugError","debugMode","initialisePage","processContent","wrap","settings","dom","wrapperID","replace","children","remove","append","tickerID","titleID","contentID","revealID","removeClass","addClass","direction","tickerElem","hide","controls","controlsID","live","e","button","target","id","type","prevID","paused","playPauseID","manualChangeContent","nextID","play","pauseTicker","restartTicker","hasClass","displayType","mouseover","mouseout","ajaxFeed","setupContentAndTriggerDisplay","contentLoaded","feedType","ajax","url","feedUrl","cache","dataType","async","success","data","count","a","childNodes","nodeName","xmlContent","xmlChannel","x","xmlItems","title","link","y","lastChild","nodeValue","newsArr","titleText","content","htmlFeed","html","titleElem","position","revealContent","distance","width","time","speed","css","offset","fadeIn","fadeInSpeed","postReveal","revealElem","show","animationAction","marginRight","marginLeft","delay","animate","pauseOnItems","fadeOut","fadeOutSpeed","find","end","removeAttr","stop","uniqID","toLowerCase"],"mappings":"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","file":"newsticker.js","sourcesContent":["(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"collective.newsticker\"] = factory();\n\telse\n\t\troot[\"collective.newsticker\"] = factory();\n})(this, function() {\nreturn \n\n\n// WEBPACK FOOTER //\n// webpack/universalModuleDefinition","(function webpackUniversalModuleDefinition(root, factory) {\n\tif(typeof exports === 'object' && typeof module === 'object')\n\t\tmodule.exports = factory();\n\telse if(typeof define === 'function' && define.amd)\n\t\tdefine([], factory);\n\telse if(typeof exports === 'object')\n\t\texports[\"collective.newsticker\"] = factory();\n\telse\n\t\troot[\"collective.newsticker\"] = factory();\n})(this, function() {\nreturn /******/ (function(modules) { // webpackBootstrap\n/******/ \t// The module cache\n/******/ \tvar installedModules = {};\n/******/\n/******/ \t// The require function\n/******/ \tfunction __webpack_require__(moduleId) {\n/******/\n/******/ \t\t// Check if module is in cache\n/******/ \t\tif(installedModules[moduleId])\n/******/ \t\t\treturn installedModules[moduleId].exports;\n/******/\n/******/ \t\t// Create a new module (and put it into the cache)\n/******/ \t\tvar module = installedModules[moduleId] = {\n/******/ \t\t\ti: moduleId,\n/******/ \t\t\tl: false,\n/******/ \t\t\texports: {}\n/******/ \t\t};\n/******/\n/******/ \t\t// Execute the module function\n/******/ \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n/******/\n/******/ \t\t// Flag the module as loaded\n/******/ \t\tmodule.l = true;\n/******/\n/******/ \t\t// Return the exports of the module\n/******/ \t\treturn module.exports;\n/******/ \t}\n/******/\n/******/\n/******/ \t// expose the modules object (__webpack_modules__)\n/******/ \t__webpack_require__.m = modules;\n/******/\n/******/ \t// expose the module cache\n/******/ \t__webpack_require__.c = installedModules;\n/******/\n/******/ \t// identity function for calling harmony imports with the correct context\n/******/ \t__webpack_require__.i = function(value) { return value; };\n/******/\n/******/ \t// define getter function for harmony exports\n/******/ \t__webpack_require__.d = function(exports, name, getter) {\n/******/ \t\tif(!__webpack_require__.o(exports, name)) {\n/******/ \t\t\tObject.defineProperty(exports, name, {\n/******/ \t\t\t\tconfigurable: false,\n/******/ \t\t\t\tenumerable: true,\n/******/ \t\t\t\tget: getter\n/******/ \t\t\t});\n/******/ \t\t}\n/******/ \t};\n/******/\n/******/ \t// getDefaultExport function for compatibility with non-harmony modules\n/******/ \t__webpack_require__.n = function(module) {\n/******/ \t\tvar getter = module && module.__esModule ?\n/******/ \t\t\tfunction getDefault() { return module['default']; } :\n/******/ \t\t\tfunction getModuleExports() { return module; };\n/******/ \t\t__webpack_require__.d(getter, 'a', getter);\n/******/ \t\treturn getter;\n/******/ \t};\n/******/\n/******/ \t// Object.prototype.hasOwnProperty.call\n/******/ \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n/******/\n/******/ \t// __webpack_public_path__\n/******/ \t__webpack_require__.p = \"++resource++collective.newsticker/\";\n/******/\n/******/ \t// Load entry module and return exports\n/******/ \treturn __webpack_require__(__webpack_require__.s = 2);\n/******/ })\n/************************************************************************/\n/******/ ([\n/* 0 */\n/***/ (function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ }),\n/* 1 */\n/***/ (function(module, exports, __webpack_require__) {\n\nmodule.exports = __webpack_require__.p + \"newsticker_icon.png\";\n\n/***/ }),\n/* 2 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\"use strict\";\n\n\n__webpack_require__(0);\n\n__webpack_require__(1);\n\n/*\n jQuery News Ticker is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, version 2 of the License.\n\n jQuery News Ticker is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License\n along with jQuery News Ticker. If not, see .\n */\n$.fn.ticker = function (options) {\n // Extend our default options with those provided.\n // Note that the first arg to extend is an empty object -\n // this is to keep from overriding our \"defaults\" object.\n var opts = $.extend({}, $.fn.ticker.defaults, options);\n\n // check that the passed element is actually in the DOM\n if ($(this).length == 0) {\n if (window.console && window.console.log) {\n window.console.log('Element does not exist in DOM!');\n } else {\n alert('Element does not exist in DOM!');\n }\n return false;\n }\n\n /* Get the id of the UL to get our news content from */\n var newsID = '#' + $(this).attr('id');\n\n /* Get the tag type - we will check this later to makde sure it is a UL tag */\n var tagType = $(this).get(0).tagName;\n\n return this.each(function () {\n // get a unique id for this ticker\n var uniqID = getUniqID();\n\n /* Internal vars */\n var settings = {\n position: 0,\n time: 0,\n distance: 0,\n newsArr: {},\n play: true,\n paused: false,\n contentLoaded: false,\n dom: {\n contentID: '#ticker-content-' + uniqID,\n titleID: '#ticker-title-' + uniqID,\n titleElem: '#ticker-title-' + uniqID + ' SPAN',\n tickerID: '#ticker-' + uniqID,\n wrapperID: '#ticker-wrapper-' + uniqID,\n revealID: '#ticker-swipe-' + uniqID,\n revealElem: '#ticker-swipe-' + uniqID + ' SPAN',\n controlsID: '#ticker-controls-' + uniqID,\n prevID: '#prev-' + uniqID,\n nextID: '#next-' + uniqID,\n playPauseID: '#play-pause-' + uniqID\n }\n };\n\n // if we are not using a UL, display an error message and stop any further execution\n if (tagType != 'UL' && tagType != 'OL' && opts.htmlFeed === true) {\n debugError('Cannot use <' + tagType.toLowerCase() + '> type of element for this plugin - must of type
or ');\n return false;\n }\n\n // set the ticker direction\n opts.direction == 'rtl' ? opts.direction = 'right' : opts.direction = 'left';\n\n // lets go...\n initialisePage();\n /* Function to get the size of an Object*/\n function countSize(obj) {\n var size = 0;\n var key = void 0;\n for (key in obj) {\n if (obj.hasOwnProperty(key)) size++;\n }\n return size;\n };\n\n function getUniqID() {\n var newDate = new Date();\n return newDate.getTime();\n }\n\n /* Function for handling debug and error messages */\n function debugError(obj) {\n if (opts.debugMode) {\n if (window.console && window.console.log) {\n window.console.log(obj);\n } else {\n alert(obj);\n }\n }\n }\n\n /* Function to setup the page */\n function initialisePage() {\n // process the content for this ticker\n processContent();\n\n // add our HTML structure for the ticker to the DOM\n $(newsID).wrap('');\n\n // remove any current content inside this ticker\n $(settings.dom.wrapperID).children().remove();\n\n $(settings.dom.wrapperID).append('
\\n
\\n \\n
\\n \\n
\\n \\n
\\n
');\n $(settings.dom.wrapperID).removeClass('no-js').addClass('ticker-wrapper has-js ' + opts.direction);\n // hide the ticker\n $(settings.dom.tickerElem + ',' + settings.dom.contentID).hide();\n // add the controls to the DOM if required\n if (opts.controls) {\n // add related events - set functions to run on given event\n $(settings.dom.controlsID).live('click mouseover mousedown mouseout mouseup', function (e) {\n var button = e.target.id;\n if (e.type == 'click') {\n switch (button) {\n case settings.dom.prevID.replace('#', ''):\n // show previous item\n settings.paused = true;\n $(settings.dom.playPauseID).addClass('paused');\n manualChangeContent('prev');\n break;\n case settings.dom.nextID.replace('#', ''):\n // show next item\n settings.paused = true;\n $(settings.dom.playPauseID).addClass('paused');\n manualChangeContent('next');\n break;\n case settings.dom.playPauseID.replace('#', ''):\n // play or pause the ticker\n if (settings.play == true) {\n settings.paused = true;\n $(settings.dom.playPauseID).addClass('paused');\n pauseTicker();\n } else {\n settings.paused = false;\n $(settings.dom.playPauseID).removeClass('paused');\n restartTicker();\n }\n break;\n }\n } else if (e.type == 'mouseover' && $('#' + button).hasClass('controls')) {\n $('#' + button).addClass('over');\n } else if (e.type == 'mousedown' && $('#' + button).hasClass('controls')) {\n $('#' + button).addClass('down');\n } else if (e.type == 'mouseup' && $('#' + button).hasClass('controls')) {\n $('#' + button).removeClass('down');\n } else if (e.type == 'mouseout' && $('#' + button).hasClass('controls')) {\n $('#' + button).removeClass('over');\n }\n });\n // add controls HTML to DOM\n $(settings.dom.wrapperID).append('
\\n
\\n
\\n
\\n
');\n }\n if (opts.displayType != 'fade') {\n // add mouse over on the content\n $(settings.dom.contentID).mouseover(function () {\n if (settings.paused == false) {\n pauseTicker();\n }\n }).mouseout(function () {\n if (settings.paused == false) {\n restartTicker();\n }\n });\n }\n // we may have to wait for the ajax call to finish here\n if (!opts.ajaxFeed) {\n setupContentAndTriggerDisplay();\n }\n }\n\n /* Start to process the content for this ticker */\n function processContent() {\n // check to see if we need to load content\n if (settings.contentLoaded == false) {\n // construct content\n if (opts.ajaxFeed) {\n if (opts.feedType == 'xml') {\n $.ajax({\n url: opts.feedUrl,\n cache: false,\n dataType: opts.feedType,\n async: true,\n success: function success(data) {\n count = 0;\n // get the 'root' node\n for (var a = 0; a < data.childNodes.length; a++) {\n if (data.childNodes[a].nodeName == 'rss') {\n xmlContent = data.childNodes[a];\n }\n }\n // find the channel node\n for (var i = 0; i < xmlContent.childNodes.length; i++) {\n if (xmlContent.childNodes[i].nodeName == 'channel') {\n xmlChannel = xmlContent.childNodes[i];\n }\n }\n // for each item create a link and add the article title as the link text\n for (var x = 0; x < xmlChannel.childNodes.length; x++) {\n if (xmlChannel.childNodes[x].nodeName == 'item') {\n xmlItems = xmlChannel.childNodes[x];\n var title = void 0;\n var link = false;\n for (var y = 0; y < xmlItems.childNodes.length; y++) {\n if (xmlItems.childNodes[y].nodeName == 'title') {\n title = xmlItems.childNodes[y].lastChild.nodeValue;\n } else if (xmlItems.childNodes[y].nodeName == 'link') {\n link = xmlItems.childNodes[y].lastChild.nodeValue;\n }\n if (title !== false && title != '' && link !== false) {\n settings.newsArr['item-' + count] = {\n type: opts.titleText,\n content: '' + title + ''\n };\n count++;\n title = false;\n link = false;\n }\n }\n }\n }\n // quick check here to see if we actually have any content - log error if not\n if (countSize(settings.newsArr < 1)) {\n debugError('Couldn\\'t find any content from the XML feed for the ticker to use!');\n return false;\n }\n settings.contentLoaded = true;\n setupContentAndTriggerDisplay();\n }\n });\n } else {\n debugError('Code Me!');\n }\n } else if (opts.htmlFeed) {\n if ($(newsID + ' LI').length > 0) {\n $(newsID + ' LI').each(function (i) {\n // maybe this could be one whole object and not an array of objects?\n settings.newsArr['item-' + i] = { type: opts.titleText, content: $(this).html() };\n });\n } else {\n debugError('Couldn\\'t find HTML any content for the ticker to use!');\n return false;\n }\n } else {\n debugError('The ticker is set to not use any types of content! Check the settings for the ticker.');\n return false;\n }\n }\n }\n\n function setupContentAndTriggerDisplay() {\n\n settings.contentLoaded = true;\n\n // update the ticker content with the correct item\n // insert news content into DOM\n $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);\n $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);\n\n // set the next content item to be used - loop round if we are at the end of the content\n if (settings.position == countSize(settings.newsArr) - 1) {\n settings.position = 0;\n } else {\n settings.position++;\n }\n\n // start the ticker animation\n revealContent();\n }\n\n // slide back cover or fade in content\n function revealContent() {\n // get the values of content and set the time of the reveal (so all reveals have the same speed regardless of content size)\n var distance = $(settings.dom.contentID).width();\n var time = distance / opts.speed;\n\n $(settings.dom.contentID).css('opacity', '1');\n if (settings.play) {\n // get the width of the title element to offset the content and reveal\n var offset = $(settings.dom.titleID).width() + 20;\n\n $(settings.dom.revealID).css(opts.direction, offset + 'px');\n // show the reveal element and start the animation\n if (opts.displayType == 'fade') {\n // fade in effect ticker\n $(settings.dom.revealID).hide(0, function () {\n $(settings.dom.contentID).css(opts.direction, offset + 'px').fadeIn(opts.fadeInSpeed, postReveal);\n });\n } else if (opts.displayType == 'scroll') {\n // to code\n } else {\n // default bbc scroll effect\n $(settings.dom.revealElem).show(0, function () {\n $(settings.dom.contentID).css(opts.direction, offset + 'px').show();\n // set our animation direction\n var animationAction = opts.direction == 'right' ? { marginRight: distance + 'px' } : { marginLeft: distance + 'px' };\n $(settings.dom.revealID).css('margin-' + opts.direction, '0px').delay(20).animate(animationAction, time, 'linear', postReveal);\n });\n }\n } else {\n return false;\n }\n };\n\n // here we hide the current content and reset the ticker elements to a default state ready for the next ticker item\n function postReveal() {\n if (settings.play) {\n // we have to separately fade the content out here to get around an IE bug - needs further investigation\n $(settings.dom.contentID).delay(opts.pauseOnItems).fadeOut(opts.fadeOutSpeed);\n // deal with the rest of the content, prepare the DOM and trigger the next ticker\n if (opts.displayType == 'fade') {\n $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {\n $(settings.dom.wrapperID).find(settings.dom.revealElem + ',' + settings.dom.contentID).hide().end().find(settings.dom.tickerID + ',' + settings.dom.revealID).show().end().find(settings.dom.tickerID + ',' + settings.dom.revealID).removeAttr('style');\n setupContentAndTriggerDisplay();\n });\n } else {\n $(settings.dom.revealID).hide(0, function () {\n $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, function () {\n $(settings.dom.wrapperID).find(settings.dom.revealElem + ',' + settings.dom.contentID).hide().end().find(settings.dom.tickerID + ',' + settings.dom.revealID).show().end().find(settings.dom.tickerID + ',' + settings.dom.revealID).removeAttr('style');\n setupContentAndTriggerDisplay();\n });\n });\n }\n } else {\n $(settings.dom.revealElem).hide();\n }\n }\n\n // pause ticker\n function pauseTicker() {\n settings.play = false;\n // stop animation and show content - must pass \"true, true\" to the stop function, or we can get some funky behaviour\n $(settings.dom.tickerID + ',' + settings.dom.revealID + ',' + settings.dom.titleID + ',' + settings.dom.titleElem + ',' + settings.dom.revealElem + ',' + settings.dom.contentID).stop(true, true);\n $(settings.dom.revealID + ',' + settings.dom.revealElem).hide();\n $(settings.dom.wrapperID).find(settings.dom.titleID + ',' + settings.dom.titleElem).show().end().find(settings.dom.contentID).show();\n }\n\n // play ticker\n function restartTicker() {\n settings.play = true;\n settings.paused = false;\n // start the ticker again\n postReveal();\n }\n\n // change the content on user input\n function manualChangeContent(direction) {\n pauseTicker();\n switch (direction) {\n case 'prev':\n if (settings.position == 0) {\n settings.position = countSize(settings.newsArr) - 2;\n } else if (settings.position == 1) {\n settings.position = countSize(settings.newsArr) - 1;\n } else {\n settings.position = settings.position - 2;\n }\n $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);\n $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);\n break;\n case 'next':\n $(settings.dom.titleElem).html(settings.newsArr['item-' + settings.position].type);\n $(settings.dom.contentID).html(settings.newsArr['item-' + settings.position].content);\n break;\n }\n // set the next content item to be used - loop round if we are at the end of the content\n if (settings.position == countSize(settings.newsArr) - 1) {\n settings.position = 0;\n } else {\n settings.position++;\n }\n }\n });\n};\n\n// plugin defaults - added as a property on our plugin function\n$.fn.ticker.defaults = {\n speed: 0.10,\n ajaxFeed: false,\n feedUrl: '',\n feedType: 'xml',\n displayType: 'reveal',\n htmlFeed: true,\n debugMode: true,\n controls: true,\n titleText: 'Latest',\n direction: 'ltr',\n pauseOnItems: 3000,\n fadeInSpeed: 600,\n fadeOutSpeed: 300\n};\n\n/***/ })\n/******/ ]);\n});\n\n\n// WEBPACK FOOTER //\n// newsticker.js"," \t// The module cache\n \tvar installedModules = {};\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId])\n \t\t\treturn installedModules[moduleId].exports;\n\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// identity function for calling harmony imports with the correct context\n \t__webpack_require__.i = function(value) { return value; };\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, {\n \t\t\t\tconfigurable: false,\n \t\t\t\tenumerable: true,\n \t\t\t\tget: getter\n \t\t\t});\n \t\t}\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"++resource++collective.newsticker/\";\n\n \t// Load entry module and return exports\n \treturn __webpack_require__(__webpack_require__.s = 2);\n\n\n\n// WEBPACK FOOTER //\n// webpack/bootstrap b1c492b02d9744a9b357","module.exports = __webpack_public_path__ + \"newsticker_icon.png\";\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./app/newsticker_icon.png\n// module id = 1\n// module chunks = 0","import './newsticker.less';\nimport './newsticker_icon.png';\n\n/*\n jQuery News Ticker is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, version 2 of the License.\n\n jQuery News Ticker is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License\n along with jQuery News Ticker. If not, see .\n */\n$.fn.ticker = function(options) {\n // Extend our default options with those provided.\n // Note that the first arg to extend is an empty object -\n // this is to keep from overriding our \"defaults\" object.\n const opts = $.extend({}, $.fn.ticker.defaults, options);\n\n // check that the passed element is actually in the DOM\n if ($(this).length == 0) {\n if (window.console && window.console.log) {\n window.console.log('Element does not exist in DOM!');\n }\n else {\n alert('Element does not exist in DOM!');\n }\n return false;\n }\n\n /* Get the id of the UL to get our news content from */\n const newsID = `#${$(this).attr('id')}`;\n\n /* Get the tag type - we will check this later to makde sure it is a UL tag */\n const tagType = $(this).get(0).tagName;\n\n return this.each(() => {\n // get a unique id for this ticker\n const uniqID = getUniqID();\n\n /* Internal vars */\n const settings = {\n position: 0,\n time: 0,\n distance: 0,\n newsArr: {},\n play: true,\n paused: false,\n contentLoaded: false,\n dom: {\n contentID: `#ticker-content-${uniqID}`,\n titleID: `#ticker-title-${uniqID}`,\n titleElem: `#ticker-title-${uniqID} SPAN`,\n tickerID : `#ticker-${uniqID}`,\n wrapperID: `#ticker-wrapper-${uniqID}`,\n revealID: `#ticker-swipe-${uniqID}`,\n revealElem: `#ticker-swipe-${uniqID} SPAN`,\n controlsID: `#ticker-controls-${uniqID}`,\n prevID: `#prev-${uniqID}`,\n nextID: `#next-${uniqID}`,\n playPauseID: `#play-pause-${uniqID}`\n }\n };\n\n // if we are not using a UL, display an error message and stop any further execution\n if (tagType != 'UL' && tagType != 'OL' && opts.htmlFeed === true) {\n debugError(`Cannot use <${tagType.toLowerCase()}> type of element for this plugin - must of type
or `);\n return false;\n }\n\n // set the ticker direction\n opts.direction == 'rtl' ? opts.direction = 'right' : opts.direction = 'left';\n\n // lets go...\n initialisePage();\n /* Function to get the size of an Object*/\n function countSize(obj) {\n let size = 0;\n let key;\n for (key in obj) {\n if (obj.hasOwnProperty(key)) size++;\n }\n return size;\n };\n\n function getUniqID() {\n const newDate = new Date;\n return newDate.getTime();\n }\n\n /* Function for handling debug and error messages */\n function debugError(obj) {\n if (opts.debugMode) {\n if (window.console && window.console.log) {\n window.console.log(obj);\n }\n else {\n alert(obj);\n }\n }\n }\n\n /* Function to setup the page */\n function initialisePage() {\n // process the content for this ticker\n processContent();\n\n // add our HTML structure for the ticker to the DOM\n $(newsID).wrap(``);\n\n // remove any current content inside this ticker\n $(settings.dom.wrapperID).children().remove();\n\n $(settings.dom.wrapperID).append(\n `
\n
\n \n
\n \n
\n \n
\n
`);\n $(settings.dom.wrapperID).removeClass('no-js').addClass(`ticker-wrapper has-js ${opts.direction}`);\n // hide the ticker\n $(`${settings.dom.tickerElem},${settings.dom.contentID}`).hide();\n // add the controls to the DOM if required\n if (opts.controls) {\n // add related events - set functions to run on given event\n $(settings.dom.controlsID).live('click mouseover mousedown mouseout mouseup', e => {\n const button = e.target.id;\n if (e.type == 'click') {\n switch (button) {\n case settings.dom.prevID.replace('#', ''):\n // show previous item\n settings.paused = true;\n $(settings.dom.playPauseID).addClass('paused');\n manualChangeContent('prev');\n break;\n case settings.dom.nextID.replace('#', ''):\n // show next item\n settings.paused = true;\n $(settings.dom.playPauseID).addClass('paused');\n manualChangeContent('next');\n break;\n case settings.dom.playPauseID.replace('#', ''):\n // play or pause the ticker\n if (settings.play == true) {\n settings.paused = true;\n $(settings.dom.playPauseID).addClass('paused');\n pauseTicker();\n }\n else {\n settings.paused = false;\n $(settings.dom.playPauseID).removeClass('paused');\n restartTicker();\n }\n break;\n }\n }\n else if (e.type == 'mouseover' && $(`#${button}`).hasClass('controls')) {\n $(`#${button}`).addClass('over');\n }\n else if (e.type == 'mousedown' && $(`#${button}`).hasClass('controls')) {\n $(`#${button}`).addClass('down');\n }\n else if (e.type == 'mouseup' && $(`#${button}`).hasClass('controls')) {\n $(`#${button}`).removeClass('down');\n }\n else if (e.type == 'mouseout' && $(`#${button}`).hasClass('controls')) {\n $(`#${button}`).removeClass('over');\n }\n });\n // add controls HTML to DOM\n $(settings.dom.wrapperID).append(\n `
\n
\n
\n
\n
`);\n }\n if (opts.displayType != 'fade') {\n // add mouse over on the content\n $(settings.dom.contentID).mouseover(() => {\n if (settings.paused == false) {\n pauseTicker();\n }\n }).mouseout(() => {\n if (settings.paused == false) {\n restartTicker();\n }\n });\n }\n // we may have to wait for the ajax call to finish here\n if (!opts.ajaxFeed) {\n setupContentAndTriggerDisplay();\n }\n }\n\n /* Start to process the content for this ticker */\n function processContent() {\n // check to see if we need to load content\n if (settings.contentLoaded == false) {\n // construct content\n if (opts.ajaxFeed) {\n if (opts.feedType == 'xml') {\n $.ajax({\n url: opts.feedUrl,\n cache: false,\n dataType: opts.feedType,\n async: true,\n success(data) {\n count = 0;\n // get the 'root' node\n for (let a = 0; a < data.childNodes.length; a++) {\n if (data.childNodes[a].nodeName == 'rss') {\n xmlContent = data.childNodes[a];\n }\n }\n // find the channel node\n for (let i = 0; i < xmlContent.childNodes.length; i++) {\n if (xmlContent.childNodes[i].nodeName == 'channel') {\n xmlChannel = xmlContent.childNodes[i];\n }\n }\n // for each item create a link and add the article title as the link text\n for (let x = 0; x < xmlChannel.childNodes.length; x++) {\n if (xmlChannel.childNodes[x].nodeName == 'item') {\n xmlItems = xmlChannel.childNodes[x];\n let title;\n let link = false;\n for (let y = 0; y < xmlItems.childNodes.length; y++) {\n if (xmlItems.childNodes[y].nodeName == 'title') {\n title = xmlItems.childNodes[y].lastChild.nodeValue;\n }\n else if (xmlItems.childNodes[y].nodeName == 'link') {\n link = xmlItems.childNodes[y].lastChild.nodeValue;\n }\n if ((title !== false && title != '') && link !== false) {\n settings.newsArr[`item-${count}`] = {\n type: opts.titleText,\n content: `${title}`\n };\n count++;\n title = false;\n link = false;\n }\n }\n }\n }\n // quick check here to see if we actually have any content - log error if not\n if (countSize(settings.newsArr < 1)) {\n debugError('Couldn\\'t find any content from the XML feed for the ticker to use!');\n return false;\n }\n settings.contentLoaded = true;\n setupContentAndTriggerDisplay();\n }\n });\n }\n else {\n debugError('Code Me!');\n }\n }\n else if (opts.htmlFeed) {\n if($(`${newsID} LI`).length > 0) {\n $(`${newsID} LI`).each(function (i) {\n // maybe this could be one whole object and not an array of objects?\n settings.newsArr[`item-${i}`] = { type: opts.titleText, content: $(this).html()};\n });\n }\n else {\n debugError('Couldn\\'t find HTML any content for the ticker to use!');\n return false;\n }\n }\n else {\n debugError('The ticker is set to not use any types of content! Check the settings for the ticker.');\n return false;\n }\n }\n }\n\n function setupContentAndTriggerDisplay() {\n\n settings.contentLoaded = true;\n\n // update the ticker content with the correct item\n // insert news content into DOM\n $(settings.dom.titleElem).html(settings.newsArr[`item-${settings.position}`].type);\n $(settings.dom.contentID).html(settings.newsArr[`item-${settings.position}`].content);\n\n // set the next content item to be used - loop round if we are at the end of the content\n if (settings.position == (countSize(settings.newsArr) -1)) {\n settings.position = 0;\n }\n else {\n settings.position++;\n }\n\n // start the ticker animation\n revealContent();\n }\n\n // slide back cover or fade in content\n function revealContent() {\n // get the values of content and set the time of the reveal (so all reveals have the same speed regardless of content size)\n var distance = $(settings.dom.contentID).width();\n var time = distance / opts.speed;\n\n $(settings.dom.contentID).css('opacity', '1');\n if(settings.play) {\n // get the width of the title element to offset the content and reveal\n const offset = $(settings.dom.titleID).width() + 20;\n\n $(settings.dom.revealID).css(opts.direction, `${offset}px`);\n // show the reveal element and start the animation\n if (opts.displayType == 'fade') {\n // fade in effect ticker\n $(settings.dom.revealID).hide(0, () => {\n $(settings.dom.contentID).css(opts.direction, `${offset}px`).fadeIn(opts.fadeInSpeed, postReveal);\n });\n }\n else if (opts.displayType == 'scroll') {\n // to code\n }\n else {\n // default bbc scroll effect\n $(settings.dom.revealElem).show(0, () => {\n $(settings.dom.contentID).css(opts.direction, `${offset}px`).show();\n // set our animation direction\n var animationAction = opts.direction == 'right' ? { marginRight: `${distance}px`} : { marginLeft: `${distance}px` };\n $(settings.dom.revealID).css(`margin-${opts.direction}`, '0px').delay(20).animate(animationAction, time, 'linear', postReveal);\n });\n }\n }\n else {\n return false;\n }\n };\n\n // here we hide the current content and reset the ticker elements to a default state ready for the next ticker item\n function postReveal() {\n if(settings.play) {\n // we have to separately fade the content out here to get around an IE bug - needs further investigation\n $(settings.dom.contentID).delay(opts.pauseOnItems).fadeOut(opts.fadeOutSpeed);\n // deal with the rest of the content, prepare the DOM and trigger the next ticker\n if (opts.displayType == 'fade') {\n $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, () => {\n $(settings.dom.wrapperID)\n .find(`${settings.dom.revealElem},${settings.dom.contentID}`)\n .hide()\n .end().find(`${settings.dom.tickerID},${settings.dom.revealID}`)\n .show()\n .end().find(`${settings.dom.tickerID},${settings.dom.revealID}`)\n .removeAttr('style');\n setupContentAndTriggerDisplay();\n });\n }\n else {\n $(settings.dom.revealID).hide(0, () => {\n $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, () => {\n $(settings.dom.wrapperID)\n .find(`${settings.dom.revealElem},${settings.dom.contentID}`)\n .hide()\n .end().find(`${settings.dom.tickerID},${settings.dom.revealID}`)\n .show()\n .end().find(`${settings.dom.tickerID},${settings.dom.revealID}`)\n .removeAttr('style');\n setupContentAndTriggerDisplay();\n });\n });\n }\n }\n else {\n $(settings.dom.revealElem).hide();\n }\n }\n\n // pause ticker\n function pauseTicker() {\n settings.play = false;\n // stop animation and show content - must pass \"true, true\" to the stop function, or we can get some funky behaviour\n $(`${settings.dom.tickerID},${settings.dom.revealID},${settings.dom.titleID},${settings.dom.titleElem},${settings.dom.revealElem},${settings.dom.contentID}`).stop(true, true);\n $(`${settings.dom.revealID},${settings.dom.revealElem}`).hide();\n $(settings.dom.wrapperID)\n .find(`${settings.dom.titleID},${settings.dom.titleElem}`).show()\n .end().find(settings.dom.contentID).show();\n }\n\n // play ticker\n function restartTicker() {\n settings.play = true;\n settings.paused = false;\n // start the ticker again\n postReveal();\n }\n\n // change the content on user input\n function manualChangeContent(direction) {\n pauseTicker();\n switch (direction) {\n case 'prev':\n if (settings.position == 0) {\n settings.position = countSize(settings.newsArr) -2;\n }\n else if (settings.position == 1) {\n settings.position = countSize(settings.newsArr) -1;\n }\n else {\n settings.position = settings.position - 2;\n }\n $(settings.dom.titleElem).html(settings.newsArr[`item-${settings.position}`].type);\n $(settings.dom.contentID).html(settings.newsArr[`item-${settings.position}`].content);\n break;\n case 'next':\n $(settings.dom.titleElem).html(settings.newsArr[`item-${settings.position}`].type);\n $(settings.dom.contentID).html(settings.newsArr[`item-${settings.position}`].content);\n break;\n }\n // set the next content item to be used - loop round if we are at the end of the content\n if (settings.position == (countSize(settings.newsArr) -1)) {\n settings.position = 0;\n }\n else {\n settings.position++;\n }\n }\n });\n};\n\n// plugin defaults - added as a property on our plugin function\n$.fn.ticker.defaults = {\n speed: 0.10,\n ajaxFeed: false,\n feedUrl: '',\n feedType: 'xml',\n displayType: 'reveal',\n htmlFeed: true,\n debugMode: true,\n controls: true,\n titleText: 'Latest',\n direction: 'ltr',\n pauseOnItems: 3000,\n fadeInSpeed: 600,\n fadeOutSpeed: 300\n};\n\n\n\n// WEBPACK FOOTER //\n// ./app/newsticker.js"],"sourceRoot":""}
\ No newline at end of file
diff --git a/src/collective/newsticker/browser/static/newsticker_icon.png b/src/collective/newsticker/browser/static/newsticker_icon.png
index 4c75d77..7f10360 100644
Binary files a/src/collective/newsticker/browser/static/newsticker_icon.png and b/src/collective/newsticker/browser/static/newsticker_icon.png differ
diff --git a/src/collective/newsticker/browser/static/ticker-style.css b/src/collective/newsticker/browser/static/ticker-style.css
deleted file mode 100644
index ca3c273..0000000
--- a/src/collective/newsticker/browser/static/ticker-style.css
+++ /dev/null
@@ -1,146 +0,0 @@
-/* Ticker Styling */
-.ticker-wrapper.has-js {
- margin: 20px 0px 20px 0px;
- padding: 0px 20px;
- width: 780px;
- height: 32px;
- display: block;
- -webkit-border-radius: 15px;
- -moz-border-radius: 15px;
- border-radius: 15px;
- background-color: #f8f0db;
- font-size: 0.75em;
-}
-.ticker {
- width: 710px;
- height: 23px;
- display: block;
- position: relative;
- overflow: hidden;
- background-color: #f8f0db;
-}
-.ticker-title {
- padding-top: 9px;
- color: #990000;
- font-weight: bold;
- background-color: #f8f0db;
- text-transform: uppercase;
-}
-.ticker-content {
- margin: 0px;
- padding-top: 9px;
- position: absolute;
- color: #1F527B;
- font-weight: bold;
- background-color: #f8f0db;
- overflow: hidden;
- white-space: nowrap;
- line-height: 1.2em;
-}
-.ticker-content:focus {
- none;
-}
-.ticker-content a {
- text-decoration: none;
- color: #1F527B;
-}
-.ticker-content a:hover {
- text-decoration: underline;
- color: #0D3059;
-}
-.ticker-swipe {
- padding-top: 9px;
- position: absolute;
- top: 0px;
- background-color: #f8f0db;
- display: block;
- width: 800px;
- height: 23px;
-}
-.ticker-swipe span {
- margin-left: 1px;
- background-color: #f8f0db;
- border-bottom: 1px solid #1F527B;
- height: 12px;
- width: 7px;
- display: block;
-}
-.ticker-controls {
- padding: 8px 0px 0px 0px;
- list-style-type: none;
- float: left;
-}
-.ticker-controls li {
- padding: 0px;
- margin-left: 5px;
- float: left;
- cursor: pointer;
- height: 16px;
- width: 16px;
- display: block;
-}
-.ticker-controls li.jnt-play-pause {
- background-image: url('../images/controls.png');
- background-position: 32px 16px;
-}
-.ticker-controls li.jnt-play-pause.over {
- background-position: 32px 32px;
-}
-.ticker-controls li.jnt-play-pause.down {
- background-position: 32px 0px;
-}
-.ticker-controls li.jnt-play-pause.paused {
- background-image: url('../images/controls.png');
- background-position: 48px 16px;
-}
-.ticker-controls li.jnt-play-pause.paused.over {
- background-position: 48px 32px;
-}
-.ticker-controls li.jnt-play-pause.paused.down {
- background-position: 48px 0px;
-}
-.ticker-controls li.jnt-prev {
- background-image: url('../images/controls.png');
- background-position: 0px 16px;
-}
-.ticker-controls li.jnt-prev.over {
- background-position: 0px 32px;
-}
-.ticker-controls li.jnt-prev.down {
- background-position: 0px 0px;
-}
-.ticker-controls li.jnt-next {
- background-image: url('../images/controls.png');
- background-position: 16px 16px;
-}
-.ticker-controls li.jnt-next.over {
- background-position: 16px 32px;
-}
-.ticker-controls li.jnt-next.down {
- background-position: 16px 0px;
-}
-.js-hidden {
- display: none;
-}
-.no-js-news {
- padding: 10px 0px 0px 45px;
- color: #F8F0DB;
-}
-.left .ticker-swipe {
- /*left: 80px;*/
-}
-.left .ticker-controls, .left .ticker-content, .left .ticker-title, .left .ticker {
- float: left;
-}
-.left .ticker-controls {
- padding-left: 6px;
-}
-.right .ticker-swipe {
- /*right: 80px;*/
-}
-.right .ticker-controls, .right .ticker-content, .right .ticker-title, .right .ticker {
- float: right;
-}
-.right .ticker-controls {
- padding-right: 6px;
-}
\ No newline at end of file
diff --git a/src/collective/newsticker/browser/templates/htmllinks_viewlet.pt b/src/collective/newsticker/browser/templates/htmllinks_viewlet.pt
index 679e185..93b50cb 100644
--- a/src/collective/newsticker/browser/templates/htmllinks_viewlet.pt
+++ b/src/collective/newsticker/browser/templates/htmllinks_viewlet.pt
@@ -1,4 +1,4 @@
+ tal:attributes="href string:${portal_url}/++resource++collective.newsticker/newsticker.css" />
diff --git a/src/collective/newsticker/profiles/default/jsregistry.xml b/src/collective/newsticker/profiles/default/jsregistry.xml
index 23aa0f9..ec1720b 100644
--- a/src/collective/newsticker/profiles/default/jsregistry.xml
+++ b/src/collective/newsticker/profiles/default/jsregistry.xml
@@ -1,5 +1,5 @@
diff --git a/src/collective/newsticker/tests/test_setup.py b/src/collective/newsticker/tests/test_setup.py
index 144895b..b7a6f4e 100644
--- a/src/collective/newsticker/tests/test_setup.py
+++ b/src/collective/newsticker/tests/test_setup.py
@@ -8,7 +8,7 @@
import unittest
-JS = '++resource++collective.newsticker/jquery.ticker.js'
+JS = '++resource++collective.newsticker/newsticker.js'
class InstallTestCase(unittest.TestCase):
diff --git a/webpack/.babelrc b/webpack/.babelrc
new file mode 100644
index 0000000..a0765e1
--- /dev/null
+++ b/webpack/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["es2015"]
+}
diff --git a/webpack/.gitignore b/webpack/.gitignore
new file mode 100644
index 0000000..a3bb814
--- /dev/null
+++ b/webpack/.gitignore
@@ -0,0 +1,3 @@
+node_modules/
+yarn.lock
+npm-debug.log
diff --git a/webpack/app/controls.png b/webpack/app/controls.png
new file mode 100644
index 0000000..08535be
Binary files /dev/null and b/webpack/app/controls.png differ
diff --git a/webpack/app/newsticker.js b/webpack/app/newsticker.js
new file mode 100644
index 0000000..eee8204
--- /dev/null
+++ b/webpack/app/newsticker.js
@@ -0,0 +1,450 @@
+import './newsticker.less';
+import './newsticker_icon.png';
+
+/*
+ jQuery News Ticker is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, version 2 of the License.
+
+ jQuery News Ticker is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with jQuery News Ticker. If not, see .
+ */
+$.fn.ticker = function(options) {
+ // Extend our default options with those provided.
+ // Note that the first arg to extend is an empty object -
+ // this is to keep from overriding our "defaults" object.
+ const opts = $.extend({}, $.fn.ticker.defaults, options);
+
+ // check that the passed element is actually in the DOM
+ if ($(this).length == 0) {
+ if (window.console && window.console.log) {
+ window.console.log('Element does not exist in DOM!');
+ }
+ else {
+ alert('Element does not exist in DOM!');
+ }
+ return false;
+ }
+
+ /* Get the id of the UL to get our news content from */
+ const newsID = `#${$(this).attr('id')}`;
+
+ /* Get the tag type - we will check this later to makde sure it is a UL tag */
+ const tagType = $(this).get(0).tagName;
+
+ return this.each(() => {
+ // get a unique id for this ticker
+ const uniqID = getUniqID();
+
+ /* Internal vars */
+ const settings = {
+ position: 0,
+ time: 0,
+ distance: 0,
+ newsArr: {},
+ play: true,
+ paused: false,
+ contentLoaded: false,
+ dom: {
+ contentID: `#ticker-content-${uniqID}`,
+ titleID: `#ticker-title-${uniqID}`,
+ titleElem: `#ticker-title-${uniqID} SPAN`,
+ tickerID : `#ticker-${uniqID}`,
+ wrapperID: `#ticker-wrapper-${uniqID}`,
+ revealID: `#ticker-swipe-${uniqID}`,
+ revealElem: `#ticker-swipe-${uniqID} SPAN`,
+ controlsID: `#ticker-controls-${uniqID}`,
+ prevID: `#prev-${uniqID}`,
+ nextID: `#next-${uniqID}`,
+ playPauseID: `#play-pause-${uniqID}`
+ }
+ };
+
+ // if we are not using a UL, display an error message and stop any further execution
+ if (tagType != 'UL' && tagType != 'OL' && opts.htmlFeed === true) {
+ debugError(`Cannot use <${tagType.toLowerCase()}> type of element for this plugin - must of type
or `);
+ return false;
+ }
+
+ // set the ticker direction
+ opts.direction == 'rtl' ? opts.direction = 'right' : opts.direction = 'left';
+
+ // lets go...
+ initialisePage();
+ /* Function to get the size of an Object*/
+ function countSize(obj) {
+ let size = 0;
+ let key;
+ for (key in obj) {
+ if (obj.hasOwnProperty(key)) size++;
+ }
+ return size;
+ };
+
+ function getUniqID() {
+ const newDate = new Date;
+ return newDate.getTime();
+ }
+
+ /* Function for handling debug and error messages */
+ function debugError(obj) {
+ if (opts.debugMode) {
+ if (window.console && window.console.log) {
+ window.console.log(obj);
+ }
+ else {
+ alert(obj);
+ }
+ }
+ }
+
+ /* Function to setup the page */
+ function initialisePage() {
+ // process the content for this ticker
+ processContent();
+
+ // add our HTML structure for the ticker to the DOM
+ $(newsID).wrap(``);
+
+ // remove any current content inside this ticker
+ $(settings.dom.wrapperID).children().remove();
+
+ $(settings.dom.wrapperID).append(
+ `
+
+
+
+
+
+
+
+
`);
+ $(settings.dom.wrapperID).removeClass('no-js').addClass(`ticker-wrapper has-js ${opts.direction}`);
+ // hide the ticker
+ $(`${settings.dom.tickerElem},${settings.dom.contentID}`).hide();
+ // add the controls to the DOM if required
+ if (opts.controls) {
+ // add related events - set functions to run on given event
+ $(settings.dom.controlsID).live('click mouseover mousedown mouseout mouseup', e => {
+ const button = e.target.id;
+ if (e.type == 'click') {
+ switch (button) {
+ case settings.dom.prevID.replace('#', ''):
+ // show previous item
+ settings.paused = true;
+ $(settings.dom.playPauseID).addClass('paused');
+ manualChangeContent('prev');
+ break;
+ case settings.dom.nextID.replace('#', ''):
+ // show next item
+ settings.paused = true;
+ $(settings.dom.playPauseID).addClass('paused');
+ manualChangeContent('next');
+ break;
+ case settings.dom.playPauseID.replace('#', ''):
+ // play or pause the ticker
+ if (settings.play == true) {
+ settings.paused = true;
+ $(settings.dom.playPauseID).addClass('paused');
+ pauseTicker();
+ }
+ else {
+ settings.paused = false;
+ $(settings.dom.playPauseID).removeClass('paused');
+ restartTicker();
+ }
+ break;
+ }
+ }
+ else if (e.type == 'mouseover' && $(`#${button}`).hasClass('controls')) {
+ $(`#${button}`).addClass('over');
+ }
+ else if (e.type == 'mousedown' && $(`#${button}`).hasClass('controls')) {
+ $(`#${button}`).addClass('down');
+ }
+ else if (e.type == 'mouseup' && $(`#${button}`).hasClass('controls')) {
+ $(`#${button}`).removeClass('down');
+ }
+ else if (e.type == 'mouseout' && $(`#${button}`).hasClass('controls')) {
+ $(`#${button}`).removeClass('over');
+ }
+ });
+ // add controls HTML to DOM
+ $(settings.dom.wrapperID).append(
+ `
+
+
+
+
`);
+ }
+ if (opts.displayType != 'fade') {
+ // add mouse over on the content
+ $(settings.dom.contentID).mouseover(() => {
+ if (settings.paused == false) {
+ pauseTicker();
+ }
+ }).mouseout(() => {
+ if (settings.paused == false) {
+ restartTicker();
+ }
+ });
+ }
+ // we may have to wait for the ajax call to finish here
+ if (!opts.ajaxFeed) {
+ setupContentAndTriggerDisplay();
+ }
+ }
+
+ /* Start to process the content for this ticker */
+ function processContent() {
+ // check to see if we need to load content
+ if (settings.contentLoaded == false) {
+ // construct content
+ if (opts.ajaxFeed) {
+ if (opts.feedType == 'xml') {
+ $.ajax({
+ url: opts.feedUrl,
+ cache: false,
+ dataType: opts.feedType,
+ async: true,
+ success(data) {
+ count = 0;
+ // get the 'root' node
+ for (let a = 0; a < data.childNodes.length; a++) {
+ if (data.childNodes[a].nodeName == 'rss') {
+ xmlContent = data.childNodes[a];
+ }
+ }
+ // find the channel node
+ for (let i = 0; i < xmlContent.childNodes.length; i++) {
+ if (xmlContent.childNodes[i].nodeName == 'channel') {
+ xmlChannel = xmlContent.childNodes[i];
+ }
+ }
+ // for each item create a link and add the article title as the link text
+ for (let x = 0; x < xmlChannel.childNodes.length; x++) {
+ if (xmlChannel.childNodes[x].nodeName == 'item') {
+ xmlItems = xmlChannel.childNodes[x];
+ let title;
+ let link = false;
+ for (let y = 0; y < xmlItems.childNodes.length; y++) {
+ if (xmlItems.childNodes[y].nodeName == 'title') {
+ title = xmlItems.childNodes[y].lastChild.nodeValue;
+ }
+ else if (xmlItems.childNodes[y].nodeName == 'link') {
+ link = xmlItems.childNodes[y].lastChild.nodeValue;
+ }
+ if ((title !== false && title != '') && link !== false) {
+ settings.newsArr[`item-${count}`] = {
+ type: opts.titleText,
+ content: `${title}`
+ };
+ count++;
+ title = false;
+ link = false;
+ }
+ }
+ }
+ }
+ // quick check here to see if we actually have any content - log error if not
+ if (countSize(settings.newsArr < 1)) {
+ debugError('Couldn\'t find any content from the XML feed for the ticker to use!');
+ return false;
+ }
+ settings.contentLoaded = true;
+ setupContentAndTriggerDisplay();
+ }
+ });
+ }
+ else {
+ debugError('Code Me!');
+ }
+ }
+ else if (opts.htmlFeed) {
+ if($(`${newsID} LI`).length > 0) {
+ $(`${newsID} LI`).each(function (i) {
+ // maybe this could be one whole object and not an array of objects?
+ settings.newsArr[`item-${i}`] = { type: opts.titleText, content: $(this).html()};
+ });
+ }
+ else {
+ debugError('Couldn\'t find HTML any content for the ticker to use!');
+ return false;
+ }
+ }
+ else {
+ debugError('The ticker is set to not use any types of content! Check the settings for the ticker.');
+ return false;
+ }
+ }
+ }
+
+ function setupContentAndTriggerDisplay() {
+
+ settings.contentLoaded = true;
+
+ // update the ticker content with the correct item
+ // insert news content into DOM
+ $(settings.dom.titleElem).html(settings.newsArr[`item-${settings.position}`].type);
+ $(settings.dom.contentID).html(settings.newsArr[`item-${settings.position}`].content);
+
+ // set the next content item to be used - loop round if we are at the end of the content
+ if (settings.position == (countSize(settings.newsArr) -1)) {
+ settings.position = 0;
+ }
+ else {
+ settings.position++;
+ }
+
+ // start the ticker animation
+ revealContent();
+ }
+
+ // slide back cover or fade in content
+ function revealContent() {
+ // get the values of content and set the time of the reveal (so all reveals have the same speed regardless of content size)
+ var distance = $(settings.dom.contentID).width();
+ var time = distance / opts.speed;
+
+ $(settings.dom.contentID).css('opacity', '1');
+ if(settings.play) {
+ // get the width of the title element to offset the content and reveal
+ const offset = $(settings.dom.titleID).width() + 20;
+
+ $(settings.dom.revealID).css(opts.direction, `${offset}px`);
+ // show the reveal element and start the animation
+ if (opts.displayType == 'fade') {
+ // fade in effect ticker
+ $(settings.dom.revealID).hide(0, () => {
+ $(settings.dom.contentID).css(opts.direction, `${offset}px`).fadeIn(opts.fadeInSpeed, postReveal);
+ });
+ }
+ else if (opts.displayType == 'scroll') {
+ // to code
+ }
+ else {
+ // default bbc scroll effect
+ $(settings.dom.revealElem).show(0, () => {
+ $(settings.dom.contentID).css(opts.direction, `${offset}px`).show();
+ // set our animation direction
+ var animationAction = opts.direction == 'right' ? { marginRight: `${distance}px`} : { marginLeft: `${distance}px` };
+ $(settings.dom.revealID).css(`margin-${opts.direction}`, '0px').delay(20).animate(animationAction, time, 'linear', postReveal);
+ });
+ }
+ }
+ else {
+ return false;
+ }
+ };
+
+ // here we hide the current content and reset the ticker elements to a default state ready for the next ticker item
+ function postReveal() {
+ if(settings.play) {
+ // we have to separately fade the content out here to get around an IE bug - needs further investigation
+ $(settings.dom.contentID).delay(opts.pauseOnItems).fadeOut(opts.fadeOutSpeed);
+ // deal with the rest of the content, prepare the DOM and trigger the next ticker
+ if (opts.displayType == 'fade') {
+ $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, () => {
+ $(settings.dom.wrapperID)
+ .find(`${settings.dom.revealElem},${settings.dom.contentID}`)
+ .hide()
+ .end().find(`${settings.dom.tickerID},${settings.dom.revealID}`)
+ .show()
+ .end().find(`${settings.dom.tickerID},${settings.dom.revealID}`)
+ .removeAttr('style');
+ setupContentAndTriggerDisplay();
+ });
+ }
+ else {
+ $(settings.dom.revealID).hide(0, () => {
+ $(settings.dom.contentID).fadeOut(opts.fadeOutSpeed, () => {
+ $(settings.dom.wrapperID)
+ .find(`${settings.dom.revealElem},${settings.dom.contentID}`)
+ .hide()
+ .end().find(`${settings.dom.tickerID},${settings.dom.revealID}`)
+ .show()
+ .end().find(`${settings.dom.tickerID},${settings.dom.revealID}`)
+ .removeAttr('style');
+ setupContentAndTriggerDisplay();
+ });
+ });
+ }
+ }
+ else {
+ $(settings.dom.revealElem).hide();
+ }
+ }
+
+ // pause ticker
+ function pauseTicker() {
+ settings.play = false;
+ // stop animation and show content - must pass "true, true" to the stop function, or we can get some funky behaviour
+ $(`${settings.dom.tickerID},${settings.dom.revealID},${settings.dom.titleID},${settings.dom.titleElem},${settings.dom.revealElem},${settings.dom.contentID}`).stop(true, true);
+ $(`${settings.dom.revealID},${settings.dom.revealElem}`).hide();
+ $(settings.dom.wrapperID)
+ .find(`${settings.dom.titleID},${settings.dom.titleElem}`).show()
+ .end().find(settings.dom.contentID).show();
+ }
+
+ // play ticker
+ function restartTicker() {
+ settings.play = true;
+ settings.paused = false;
+ // start the ticker again
+ postReveal();
+ }
+
+ // change the content on user input
+ function manualChangeContent(direction) {
+ pauseTicker();
+ switch (direction) {
+ case 'prev':
+ if (settings.position == 0) {
+ settings.position = countSize(settings.newsArr) -2;
+ }
+ else if (settings.position == 1) {
+ settings.position = countSize(settings.newsArr) -1;
+ }
+ else {
+ settings.position = settings.position - 2;
+ }
+ $(settings.dom.titleElem).html(settings.newsArr[`item-${settings.position}`].type);
+ $(settings.dom.contentID).html(settings.newsArr[`item-${settings.position}`].content);
+ break;
+ case 'next':
+ $(settings.dom.titleElem).html(settings.newsArr[`item-${settings.position}`].type);
+ $(settings.dom.contentID).html(settings.newsArr[`item-${settings.position}`].content);
+ break;
+ }
+ // set the next content item to be used - loop round if we are at the end of the content
+ if (settings.position == (countSize(settings.newsArr) -1)) {
+ settings.position = 0;
+ }
+ else {
+ settings.position++;
+ }
+ }
+ });
+};
+
+// plugin defaults - added as a property on our plugin function
+$.fn.ticker.defaults = {
+ speed: 0.10,
+ ajaxFeed: false,
+ feedUrl: '',
+ feedType: 'xml',
+ displayType: 'reveal',
+ htmlFeed: true,
+ debugMode: true,
+ controls: true,
+ titleText: 'Latest',
+ direction: 'ltr',
+ pauseOnItems: 3000,
+ fadeInSpeed: 600,
+ fadeOutSpeed: 300
+};
diff --git a/webpack/app/newsticker.less b/webpack/app/newsticker.less
new file mode 100644
index 0000000..7a6e847
--- /dev/null
+++ b/webpack/app/newsticker.less
@@ -0,0 +1,180 @@
+// Color variables (appears count calculates by raw css)
+@color0: #F8F0DB; // Appears 7 times
+@color1: #1F527B; // Appears 3 times
+
+
+// Height variables (appears count calculates by raw css)
+@height2: 23px; // Appears 2 times
+
+.ticker-wrapper.has-js {
+ font-size: .75em;
+
+ display: block;
+
+ width: 780px;
+ height: 32px;
+ margin: 20px 0 20px 0;
+ padding: 0 20px;
+
+ -webkit-border-radius: 15px;
+ -moz-border-radius: 15px;
+ border-radius: 15px;
+ background-color: @color0;
+}
+.ticker {
+ position: relative;
+
+ display: block;
+ overflow: hidden;
+
+ width: 710px;
+ height: @height2;
+
+ background-color: @color0;
+}
+.ticker-title {
+ font-weight: bold;
+
+ padding-top: 9px;
+
+ text-transform: uppercase;
+
+ color: #900;
+ background-color: @color0;
+}
+.ticker-content {
+ font-weight: bold;
+ line-height: 1.2em;
+
+ position: absolute;
+
+ overflow: hidden;
+
+ margin: 0;
+ padding-top: 9px;
+
+ white-space: nowrap;
+
+ color: @color1;
+ background-color: @color0;
+ a {
+ text-decoration: none;
+
+ color: @color1;
+ &:hover {
+ text-decoration: underline;
+
+ color: #0D3059;
+ }
+ }
+}
+.ticker-swipe {
+ position: absolute;
+ top: 0;
+
+ display: block;
+
+ width: 800px;
+ height: @height2;
+ padding-top: 9px;
+
+ background-color: @color0;
+ span {
+ display: block;
+
+ width: 7px;
+ height: 12px;
+ margin-left: 1px;
+
+ border-bottom: 1px solid @color1;
+ background-color: @color0;
+ }
+}
+.ticker-controls {
+ float: left;
+
+ padding: 8px 0 0 0;
+
+ list-style-type: none;
+ li {
+ display: block;
+ float: left;
+
+ width: 16px;
+ height: 16px;
+ margin-left: 5px;
+ padding: 0;
+
+ cursor: pointer;
+ }
+ li.jnt-play-pause {
+ background-image: url('controls.png');
+ background-position: 32px 16px;
+ }
+ li.jnt-play-pause.over {
+ background-position: 32px 32px;
+ }
+ li.jnt-play-pause.down {
+ background-position: 32px 0;
+ }
+ li.jnt-play-pause.paused {
+ background-image: url('controls.png');
+ background-position: 48px 16px;
+ }
+ li.jnt-play-pause.paused.over {
+ background-position: 48px 32px;
+ }
+ li.jnt-play-pause.paused.down {
+ background-position: 48px 0;
+ }
+ li.jnt-prev {
+ background-image: url('controls.png');
+ background-position: 0 16px;
+ }
+ li.jnt-prev.over {
+ background-position: 0 32px;
+ }
+ li.jnt-prev.down {
+ background-position: 0 0;
+ }
+ li.jnt-next {
+ background-image: url('controls.png');
+ background-position: 16px 16px;
+ }
+ li.jnt-next.over {
+ background-position: 16px 32px;
+ }
+ li.jnt-next.down {
+ background-position: 16px 0;
+ }
+}
+.js-hidden {
+ display: none;
+}
+.no-js-news {
+ padding: 10px 0 0 45px;
+
+ color: @color0;
+}
+.left {
+ .ticker-controls {
+ padding-left: 6px;
+ }
+}
+.left .ticker-controls,
+.left .ticker-content,
+.left .ticker-title,
+.left .ticker {
+ float: left;
+}
+.right {
+ .ticker-controls {
+ padding-right: 6px;
+ }
+}
+.right .ticker-controls,
+.right .ticker-content,
+.right .ticker-title,
+.right .ticker {
+ float: right;
+}
diff --git a/webpack/app/newsticker_icon.png b/webpack/app/newsticker_icon.png
new file mode 100644
index 0000000..4c75d77
Binary files /dev/null and b/webpack/app/newsticker_icon.png differ
diff --git a/webpack/package.json b/webpack/package.json
new file mode 100644
index 0000000..14881dd
--- /dev/null
+++ b/webpack/package.json
@@ -0,0 +1,28 @@
+{
+ "name": "collective.newsticker",
+ "version": "1.0.0",
+ "main": "app/newsticker.js",
+ "scripts": {
+ "dev": "webpack",
+ "build": "webpack -p",
+ "watch": "webpack -p --watch"
+ },
+ "repository": {},
+ "license": "GPLv2",
+ "devDependencies": {
+ "babel-core": "^6.22.1",
+ "babel-loader": "^6.2.10",
+ "babel-preset-es2015": "^6.22.0",
+ "css-loader": "^0.26.1",
+ "extract-text-webpack-plugin": "^2.0.0-beta",
+ "file-loader": "^0.9.0",
+ "image-webpack-loader": "^3.1.0",
+ "less": "^2.7.2",
+ "less-loader": "^2.2.3",
+ "postcss": "^5.2.11",
+ "postcss-cssnext": "^2.9.0",
+ "postcss-loader": "^1.2.2",
+ "style-loader": "^0.13.1",
+ "svg-url-loader": "^2.0.1"
+ }
+}
diff --git a/webpack/postcss.config.js b/webpack/postcss.config.js
new file mode 100644
index 0000000..e1db6a1
--- /dev/null
+++ b/webpack/postcss.config.js
@@ -0,0 +1,7 @@
+module.exports = {
+ plugins: {
+ 'postcss-cssnext': {
+ browsers: 'last 3 versions'
+ },
+ },
+};
diff --git a/webpack/webpack.config.js b/webpack/webpack.config.js
new file mode 100644
index 0000000..17fc219
--- /dev/null
+++ b/webpack/webpack.config.js
@@ -0,0 +1,54 @@
+var ExtractTextPlugin = require('extract-text-webpack-plugin');
+module.exports = {
+ entry: './app/newsticker.js',
+ output: {
+ filename: 'newsticker.js',
+ path: '../src/collective/newsticker/browser/static',
+ libraryTarget: 'umd',
+ publicPath: '++resource++collective.newsticker/',
+ library: 'collective.newsticker'
+ },
+ module: {
+ rules: [{
+ test: /\.js$/,
+ exclude: /(\/node_modules\/|test\.js$|\.spec\.js$)/,
+ use: 'babel-loader',
+ }, {
+ test: /\.less$/,
+ exclude: /node_modules/,
+ loader: ExtractTextPlugin.extract({
+ fallbackLoader: 'style-loader',
+ loader: 'css-loader?importLoaders=1!postcss-loader!less-loader'
+ })
+ }, {
+ test: /.*\.(gif|png|jpe?g)$/i,
+ loaders: [
+ 'file-loader?name=[path][name].[ext]&context=app/',
+ {
+ loader: 'image-webpack-loader',
+ query: {
+ progressive: true,
+ pngquant: {
+ quality: '65-90',
+ speed: 4
+ },
+ gifsicle: {
+ interlaced: false
+ },
+ optipng: {
+ optimizationLevel: 7
+ }
+ }
+ }
+ ]
+ }, {
+ test: /\.svg/,
+ exclude: /node_modules/,
+ use: 'svg-url-loader'
+ }]
+ },
+ devtool: 'source-map',
+ plugins: [
+ new ExtractTextPlugin({ filename: 'newsticker.css', disable: false, allChunks: true })
+ ]
+}