jquery.webticker.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. /*!
  2. * webTicker 2.2.0
  3. * Examples and documentation at:
  4. * http://jonmifsud.com/open-source/jquery/jquery-webticker/
  5. * 2011 Jonathan Mifsud
  6. * Version: 2.2.0 (15-FEB-2016)
  7. * Dual licensed under the Creative Commons and DonationWare licenses:
  8. * http://creativecommons.org/licenses/by-nc/3.0/
  9. * https://github.com/jonmifsud/Web-Ticker/blob/master/licence.md
  10. * Requires:
  11. * jQuery v1.4.2 or later
  12. *
  13. */
  14. (function( $ ){
  15. var cssTransitionsSupported = (function() {
  16. var s = document.createElement('p').style,
  17. v = ['ms','O','Moz','Webkit'];
  18. if( s.transition === '' ){ return true; }
  19. while( v.length ){
  20. if( v.pop() + 'Transition' in s ){
  21. return true;
  22. }
  23. }
  24. return false;
  25. })();
  26. function getStripWidth($strip){
  27. var stripWidth=0;
  28. $strip.children('li').each(function(){
  29. stripWidth += $(this).outerWidth( true );
  30. });
  31. return stripWidth;
  32. }
  33. function getItemWidth($strip){
  34. return Math.max.apply(Math, $strip.children().map(function(){ return $(this).width(); }).get());
  35. }
  36. function animationSettings($strip){
  37. var settings = $strip.data('settings') || { direction: 'left', speed: 50 };
  38. var first = $strip.children().first();
  39. var distance = Math.abs(-$strip.css(settings.direction).replace('px','').replace('auto','0') - first.outerWidth(true));
  40. var timeToComplete = distance * 1000 / settings.speed;
  41. var animationSettings = {};
  42. animationSettings[settings.direction] = $strip.css(settings.direction).replace('px','').replace('auto','0') - distance;
  43. return {'css':animationSettings,'time':timeToComplete};
  44. }
  45. function moveFirstElement($strip){
  46. var settings = $strip.data('settings') || { direction: 'left' };
  47. $strip.css('transition-duration','0s').css(settings.direction, '0');
  48. var $first = $strip.children().first();
  49. if ($first.hasClass('webticker-init')){
  50. $first.remove();
  51. }
  52. else{
  53. $strip.children().last().after($first);
  54. }
  55. }
  56. function scrollitems($strip,moveFirst){
  57. var settings = $strip.data('settings') || { direction: 'left' };
  58. if (typeof moveFirst === 'undefined'){
  59. moveFirst = false;
  60. }
  61. if (moveFirst){
  62. moveFirstElement($strip);
  63. }
  64. var options = animationSettings($strip);
  65. $strip.animate(options.css, options.time, 'linear', function(){
  66. $strip.css(settings.direction, '0');
  67. scrollitems($strip,true);
  68. });
  69. }
  70. function css3Scroll($strip,moveFirst){
  71. if (typeof moveFirst === 'undefined'){
  72. moveFirst = false;
  73. }
  74. if (moveFirst){
  75. moveFirstElement($strip);
  76. }
  77. var options = animationSettings($strip);
  78. var time = options.time/1000;
  79. time += 's';
  80. $strip.css(options.css).css('transition-duration',time);
  81. }
  82. function updaterss(rssurl,type,$strip){
  83. var list = [];
  84. $.get(rssurl, function(data) {
  85. var $xml = $(data);
  86. $xml.find('item').each(function() {
  87. var $this = $(this),
  88. item = {
  89. title: $this.find('title').text(),
  90. link: $this.find('link').text()
  91. };
  92. var listItem = '<li><a href="'+item.link+'"">'+item.title+'</a></li>';
  93. list += listItem;
  94. //Do something with item here...
  95. });
  96. $strip.webTicker('update', list, type);
  97. });
  98. }
  99. function initialize($strip, init){
  100. if ($strip.children('li').length < 1) {
  101. if (window.console) {
  102. // console.log('no items to initialize');
  103. }
  104. return false;
  105. }
  106. var settings = $strip.data('settings');
  107. settings.duplicateLoops = settings.duplicateLoops || 0;
  108. $strip.width('auto');
  109. //Find the real width of all li elements
  110. var stripWidth = 0;
  111. $strip.children('li').each(function(){
  112. stripWidth += $(this).outerWidth( true );
  113. });
  114. var height = $strip.find('li:first').height();
  115. var itemWidth;
  116. // if(stripWidth < $strip.parent().width() || $strip.children().length == 1){
  117. //if duplicate items
  118. if (settings.duplicate){
  119. //Check how many times to duplicate depending on width.
  120. itemWidth = getItemWidth($strip);
  121. var duplicateLoops = 0;
  122. while (stripWidth - itemWidth < $strip.parent().width() || $strip.children().length === 1 || duplicateLoops < settings.duplicateLoops){
  123. var listItems = $strip.children().clone();
  124. $strip.append(listItems);
  125. stripWidth = 0;
  126. stripWidth = getStripWidth($strip);
  127. itemWidth = getItemWidth($strip);
  128. duplicateLoops++;
  129. }
  130. settings.duplicateLoops = duplicateLoops;
  131. }else {
  132. //if fill with empty padding
  133. var emptySpace = $strip.parent().width() - stripWidth;
  134. emptySpace += $strip.find('li:first').width();
  135. // $strip.append('<li class="ticker-spacer" style="width:'+emptySpace+'px;height:'+height+'px;"></li>');
  136. if ($strip.find('.ticker-spacer').length > 0){
  137. // console.log('test');
  138. $strip.find('.ticker-spacer').width(emptySpace);
  139. }
  140. else{
  141. // console.log('test2');
  142. $strip.append('<li class="ticker-spacer" style="float: '+settings.direction+';width:'+emptySpace+'px;height:'+height+'px;"></li>');
  143. }
  144. // }
  145. }
  146. if (settings.startEmpty && init){
  147. $strip.prepend('<li class="webticker-init" style="float: '+settings.direction+';width:'+$strip.parent().width()+'px;height:'+height+'px;"></li>');
  148. }
  149. //extra width to be able to move items without any jumps $strip.find("li:first").width()
  150. stripWidth = 0;
  151. stripWidth = getStripWidth($strip);
  152. $strip.width(stripWidth+200);
  153. var widthCompare = 0;
  154. widthCompare = getStripWidth($strip);
  155. //loop to find weather the items inside the list are actually bigger then the size of the whole list. Increments in 200px.
  156. //only required when a single item is bigger then the whole list
  157. while (widthCompare >= $strip.width()){
  158. $strip.width($strip.width()+200);
  159. widthCompare = 0;
  160. widthCompare = getStripWidth($strip);
  161. }
  162. return true;
  163. }
  164. var methods = {
  165. init : function( settings ) { // THIS
  166. settings = jQuery.extend({
  167. speed: 50, //pixels per second
  168. direction: 'left',
  169. moving: true,
  170. startEmpty: true,
  171. duplicate: false,
  172. rssurl: false,
  173. hoverpause: true,
  174. rssfrequency: 0,
  175. updatetype: 'reset',
  176. transition: 'linear',
  177. height: '30px',
  178. maskleft: '', // maskleft and maskright require a width setting in your css to work
  179. maskright: '',
  180. maskwidth: 0
  181. }, settings);
  182. //set data-ticker a unique ticker identifier if it does not exist
  183. return this.each(function(){
  184. jQuery(this).data('settings',settings);
  185. var $strip = jQuery(this);
  186. var $mask = $strip.wrap('<div class="mask"></div>');
  187. $mask.after('<span class="tickeroverlay-left">&nbsp;</span><span class="tickeroverlay-right">&nbsp;</span>');
  188. var $tickercontainer = $strip.parent().wrap('<div class="tickercontainer"></div>');
  189. var resizeEvt;
  190. $(window).resize(function() {
  191. clearTimeout(resizeEvt);
  192. resizeEvt = setTimeout(function() {
  193. console.log('window was resized');
  194. initialize($strip,false);
  195. }, 500);
  196. });
  197. //adding required css rules
  198. $strip.children('li').css('white-space','nowrap');
  199. $strip.children('li').css('float',settings.direction);
  200. $strip.children('li').css('padding','0 7px');
  201. $strip.children('li').css('line-height',settings.height);
  202. $mask.css('position','relative');
  203. $mask.css('overflow','hidden');
  204. $strip.closest('.tickercontainer').css('height', settings.height);
  205. $strip.closest('.tickercontainer').css('overflow', 'hidden');
  206. $strip.css('float',settings.direction);
  207. $strip.css('position','relative');
  208. $strip.css('font', 'bold 10px Verdana');
  209. $strip.css('list-style-type', 'none');
  210. $strip.css('margin', '0');
  211. $strip.css('padding', '0');
  212. if ((settings.maskleft !== '') && (settings.maskright !== '')){
  213. var backgroundimage='url("'+settings.maskleft+'")';
  214. $tickercontainer.find('.tickeroverlay-left').css('background-image',backgroundimage);
  215. $tickercontainer.find('.tickeroverlay-left').css('display','block');
  216. $tickercontainer.find('.tickeroverlay-left').css('pointer-events','none');
  217. $tickercontainer.find('.tickeroverlay-left').css('position','absolute');
  218. $tickercontainer.find('.tickeroverlay-left').css('z-index','30');
  219. $tickercontainer.find('.tickeroverlay-left').css('height',settings.height);
  220. $tickercontainer.find('.tickeroverlay-left').css('width',settings.maskwidth);
  221. $tickercontainer.find('.tickeroverlay-left').css('top','0');
  222. $tickercontainer.find('.tickeroverlay-left').css('left','-2px');
  223. backgroundimage='url("'+settings.maskright+'")';
  224. $tickercontainer.find('.tickeroverlay-right').css('background-image',backgroundimage);
  225. $tickercontainer.find('.tickeroverlay-right').css('display','block');
  226. $tickercontainer.find('.tickeroverlay-right').css('pointer-events','none');
  227. $tickercontainer.find('.tickeroverlay-right').css('position','absolute');
  228. $tickercontainer.find('.tickeroverlay-right').css('z-index','30');
  229. $tickercontainer.find('.tickeroverlay-right').css('height',settings.height);
  230. $tickercontainer.find('.tickeroverlay-right').css('width',settings.maskwidth);
  231. $tickercontainer.find('.tickeroverlay-right').css('top','0');
  232. $tickercontainer.find('.tickeroverlay-right').css('right','-2px');
  233. }
  234. else{
  235. $tickercontainer.find('.tickeroverlay-left').css('display','none');
  236. $tickercontainer.find('.tickeroverlay-right').css('display','none');
  237. }
  238. //adding the 'last' class will help for future duplicate functions
  239. $strip.children('li').last().addClass('last');
  240. var started = initialize($strip,true);
  241. if (settings.rssurl){
  242. updaterss(settings.rssurl,settings.type,$strip);
  243. if (settings.rssfrequency>0){
  244. window.setInterval(function(){updaterss(settings.rssurl,settings.type,$strip);},settings.rssfrequency*1000*60);
  245. }
  246. }
  247. if (cssTransitionsSupported){
  248. //fix for firefox not animating default transitions
  249. $strip.css('transition-timing-function',settings.transition);
  250. $strip.css('transition-duration','0s').css(settings.direction, '0');
  251. if (started){
  252. //if list has items and set up start scrolling
  253. css3Scroll($strip,false);
  254. }
  255. //started or not still bind on the transition end event so it works after update
  256. $strip.on('transitionend webkitTransitionEnd oTransitionEnd otransitionend', function(event) {
  257. if (!$strip.is(event.target)) {
  258. return false;
  259. }
  260. css3Scroll($(this),true);
  261. });
  262. } else {
  263. if (started){
  264. //if list has items and set up start scrolling
  265. scrollitems($(this));
  266. }
  267. }
  268. if (settings.hoverpause){
  269. $strip.hover(function(){
  270. if (cssTransitionsSupported){
  271. var currentPosition = $(this).css(settings.direction);
  272. $(this).css('transition-duration','0s').css(settings.direction,currentPosition);
  273. } else{
  274. jQuery(this).stop();
  275. }
  276. },
  277. function(){
  278. if (jQuery(this).data('settings').moving){
  279. if (cssTransitionsSupported){
  280. css3Scroll($(this),false);
  281. // $(this).css("-webkit-animation-play-state", "running");
  282. } else {
  283. //usual continue stuff
  284. scrollitems($strip);
  285. }
  286. }
  287. });
  288. }
  289. });
  290. },
  291. stop : function( ) {
  292. var settings = $(this).data('settings');
  293. if (settings.moving){
  294. settings.moving = false;
  295. return this.each(function(){
  296. if (cssTransitionsSupported){
  297. var currentPosition = $(this).css(settings.direction);
  298. $(this).css('transition-duration','0s').css(settings.direction,currentPosition);
  299. } else{
  300. $(this).stop();
  301. }
  302. });
  303. }
  304. },
  305. cont : function( ) {
  306. var settings = $(this).data('settings');
  307. if (!settings.moving){
  308. settings.moving = true;
  309. return this.each(function(){
  310. if (cssTransitionsSupported){
  311. css3Scroll($(this),false);
  312. } else {
  313. scrollitems($(this));
  314. }
  315. });
  316. }
  317. },
  318. transition : function(transition){
  319. var $strip = $(this);
  320. if (cssTransitionsSupported){
  321. //fix for firefox not animating default transitions
  322. $strip.css('transition-timing-function',transition);
  323. }
  324. },
  325. update : function( list, type, insert, remove) {
  326. type = type || 'reset';
  327. if (typeof insert === 'undefined'){
  328. insert = true;
  329. }
  330. if (typeof remove === 'undefined'){
  331. remove = false;
  332. }
  333. if( typeof list === 'string' ) {
  334. list = $(list);
  335. }
  336. var $strip = $(this);
  337. $strip.webTicker('stop');
  338. var settings = $(this).data('settings');
  339. if (type === 'reset'){
  340. //this does a 'restart of the ticker'
  341. $strip.html(list);
  342. initialize($strip,true);
  343. } else if (type === 'swap'){
  344. var id;
  345. var match;
  346. var $listItem;
  347. var stripWidth;
  348. if (window.console) {
  349. // console.log('trying to update');
  350. }
  351. if ($strip.children('li').length < 1){
  352. //no <li> items found. Treat as new
  353. $strip.html(list);
  354. $strip.css(settings.direction, '0');
  355. initialize($strip,true);
  356. }
  357. else if (settings.duplicate === true)
  358. {
  359. // should the update be a 'hot-swap' or use replacement for IDs (in which case remove new ones)
  360. $strip.children('li').addClass('old');
  361. for (var i = list.length - 1; i >= 0; i--) {
  362. id = $(list[i]).data('update');
  363. match = $strip.find('[data-update="'+id+'"]');//should try find the id or data-attribute.
  364. if (match.length < 1){
  365. if (insert){
  366. //we need to move this item into the dom
  367. if ($strip.find('.ticker-spacer:first-child').length === 0 && $strip.find('.ticker-spacer').length > 0){
  368. $strip.children('li.ticker-spacer').before(list[i]);
  369. }
  370. else {
  371. //check for last class ...
  372. //$strip.append(list[i]));
  373. $listItem = $(list[i]);
  374. if(i===list.length-1)
  375. {
  376. $listItem.addClass('last');
  377. }
  378. $strip.find('last').after($listItem);
  379. $strip.find('last').removeClass('last');
  380. }
  381. }
  382. } else{
  383. $strip.find('[data-update="'+id+'"]').replaceWith(list[i]);
  384. }
  385. }
  386. $strip.children('li.webticker-init, li.ticker-spacer').removeClass('old');
  387. if (remove){
  388. $strip.children('li').remove('.old');
  389. }
  390. stripWidth = 0;
  391. stripWidth = getStripWidth($strip);
  392. $strip.width(stripWidth+200);
  393. //resetting $strip so that duplication works according to new width
  394. if ($strip.find('li.webticker-init').length < 1){ // checks if the strip's width is populated and handles the update accordingly
  395. settings.startEmpty=false;
  396. }
  397. $strip.html(list);
  398. //setting the css rules
  399. $strip.children('li').css('white-space','nowrap');
  400. $strip.children('li').css('float',settings.direction);
  401. $strip.children('li').css('padding','0 7px');
  402. $strip.children('li').css('line-height',settings.height);
  403. initialize($strip,true);
  404. }
  405. else
  406. {
  407. // should the update be a 'hot-swap' or use replacement for IDs (in which case remove new ones)
  408. $strip.children('li').addClass('old');
  409. for (var x = 0 ; x < list.length; x++) {
  410. id = $(list[x]).data('update');
  411. match = $strip.find('[data-update="'+id+'"]');//should try find the id or data-attribute.
  412. if (match.length < 1){
  413. if (insert){
  414. //we need to move this item into the dom
  415. if ($strip.find('.ticker-spacer:first-child').length === 0 && $strip.find('.ticker-spacer').length > 0){
  416. $strip.children('li.ticker-spacer').before(list[x]);
  417. }
  418. else {
  419. //check for last class ...
  420. //$strip.append(list[i]));
  421. $listItem = $(list[x]);
  422. if(x===list.length-1)
  423. {
  424. $listItem.addClass('last');
  425. }
  426. $strip.find('.old.last').after($listItem);
  427. $strip.find('.old.last').removeClass('last');
  428. }
  429. }
  430. } else {
  431. $strip.find('[data-update="'+id+'"]').replaceWith(list[x]);
  432. }
  433. }
  434. $strip.children('li.webticker-init, li.ticker-spacer').removeClass('old');
  435. //setting the css rules
  436. $strip.children('li').css('white-space','nowrap');
  437. $strip.children('li').css('float',settings.direction);
  438. $strip.children('li').css('padding','0 7px');
  439. $strip.children('li').css('line-height',settings.height);
  440. if (remove){
  441. $strip.children('li').remove('.old');
  442. }
  443. stripWidth = 0;
  444. stripWidth = getStripWidth($strip);
  445. $strip.width(stripWidth+200);
  446. }
  447. }
  448. $strip.webTicker('cont');
  449. }
  450. };
  451. $.fn.webTicker = function( method ) {
  452. // Method calling logic
  453. if ( methods[method] ) {
  454. return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
  455. } else if ( typeof method === 'object' || ! method ) {
  456. return methods.init.apply( this, arguments );
  457. } else {
  458. $.error( 'Method ' + method + ' does not exist on jQuery.webTicker' );
  459. }
  460. };
  461. })( jQuery );