master
1/*!
2 * webTicker 2.1.1
3 * Examples and documentation at:
4 * http://jonmifsud.com/open-source/jquery/jquery-webticker/
5 * 2011 Jonathan Mifsud
6 * Version: 2.1.1 (23-MAY-2013)
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
16 var cssTransitionsSupported = (function() {
17 var s = document.createElement('p').style,
18 v = ['ms','O','Moz','Webkit'];
19
20 if( s['transition'] == '' ) return true;
21 while( v.length )
22 if( v.pop() + 'Transition' in s )
23 return true;
24 return false;
25 })();
26
27 function scrollitems($strip,moveFirst){
28 var settings = $strip.data('settings') || { direction: "left" };
29 if (typeof moveFirst === 'undefined')
30 moveFirst = false;
31 if (moveFirst){
32 moveFirstElement($strip);
33 }
34 var options = animationSettings($strip);
35 $strip.animate(options.css, options.time, "linear", function(){
36 $strip.css(settings.direction, '0');
37 scrollitems($strip,true);
38 });
39 }
40
41 function animationSettings($strip){
42 var settings = $strip.data('settings') || { direction: "left", speed: 50 };
43 var first = $strip.children().first();
44 var distance = Math.abs(-$strip.css(settings.direction).replace('px','').replace('auto','0') - first.outerWidth(true));
45 var settings = $strip.data('settings');
46 var timeToComplete = distance * 1000 / settings.speed;
47 var animationSettings = {};
48 animationSettings[settings.direction] = $strip.css(settings.direction).replace('px','').replace('auto','0') - distance;
49 return {'css':animationSettings,'time':timeToComplete};
50 }
51
52 function moveFirstElement($strip){
53 var settings = $strip.data('settings') || { direction: "left" };
54 $strip.css('transition-duration','0s').css(settings.direction, '0');
55 var $first = $strip.children().first();
56 if ($first.hasClass('webticker-init'))
57 $first.remove();
58 else
59 $strip.children().last().after($first);
60 }
61
62 function css3Scroll($strip,moveFirst){
63 if (typeof moveFirst === 'undefined')
64 moveFirst = false;
65 if (moveFirst){
66 moveFirstElement($strip);
67 }
68 var options = animationSettings($strip);
69 var time = options.time/1000;
70 time += 's';
71 $strip.css(options.css).css('transition-duration',time);
72 }
73
74 function updaterss(rssurl,type,$strip){
75 var list = [];
76 $.get(rssurl, function(data) {
77 var $xml = $(data);
78 $xml.find("item").each(function() {
79 var $this = $(this),
80 item = {
81 title: $this.find("title").text(),
82 link: $this.find("link").text()
83 }
84 listItem = "<li><a href='"+item.link+"'>"+item.title+"</a></li>";
85 list += listItem;
86 //Do something with item here...
87 });
88 $strip.webTicker('update', list, type);
89 });
90 }
91
92 function initalize($strip){
93 if ($strip.children('li').length < 1) {
94 if (window.console) {
95 console.log('no items to initialize');
96 }
97 return false;
98 }
99
100 var settings = $strip.data('settings');
101 settings.duplicateLoops = settings.duplicateLoops || 0;
102
103 $strip.width('auto');
104
105 //Find the real width of all li elements
106 var stripWidth = 0;
107 $strip.children('li').each(function(){
108 stripWidth += $(this).outerWidth( true );
109 });
110
111 if(stripWidth < $strip.parent().width() || $strip.children().length == 1){
112 //if duplicate items
113 if (settings.duplicate){
114 //Check how many times to duplicate depending on width.
115 itemWidth = Math.max.apply(Math, $strip.children().map(function(){ return $(this).width(); }).get());
116 var duplicateLoops = 0;
117 while (stripWidth - itemWidth < $strip.parent().width() || $strip.children().length == 1 || duplicateLoops < settings.duplicateLoops){
118 var listItems = $strip.children().clone();
119 $strip.append(listItems);
120 stripWidth = 0;
121 $strip.children('li').each(function(){
122 stripWidth += $(this).outerWidth( true );
123 });
124 itemWidth = Math.max.apply(Math, $strip.children().map(function(){ return $(this).width(); }).get());
125 duplicateLoops++;
126 }
127 settings.duplicateLoops = duplicateLoops;
128 }else {
129 //if fill with empty padding
130 var emptySpace = $strip.parent().width() - stripWidth;
131 emptySpace += $strip.find("li:first").width();
132 var height = $strip.find("li:first").height();
133
134 $strip.append('<li class="ticker-spacer" style="width:'+emptySpace+'px;height:'+height+'px;"></li>');
135 }
136 }
137 if (settings.startEmpty){
138 var height = $strip.find("li:first").height();
139 $strip.prepend('<li class="webticker-init" style="width:'+$strip.parent().width()+'px;height:'+height+'px;"></li>');
140 }
141 //extra width to be able to move items without any jumps $strip.find("li:first").width()
142
143 stripWidth = 0;
144 $strip.children('li').each(function(){
145 stripWidth += $(this).outerWidth( true );
146 });
147 $strip.width(stripWidth+200);
148 widthCompare = 0;
149 $strip.children('li').each(function(){
150 widthCompare += $(this).outerWidth( true );
151 });
152 //loop to find weather the items inside the list are actually bigger then the size of the whole list. Increments in 200px.
153 //only required when a single item is bigger then the whole list
154 while (widthCompare >= $strip.width()){
155 $strip.width($strip.width()+200);
156 widthCompare = 0;
157 $strip.children('li').each(function(){
158 widthCompare += $(this).outerWidth( true );
159 });
160 }
161 return true;
162 }
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 }, settings);
177 //set data-ticker a unique ticker identifier if it does not exist
178 return this.each(function(){
179 jQuery(this).data('settings',settings);
180
181 var $strip = jQuery(this);
182 $strip.addClass("newsticker");
183 var $mask = $strip.wrap("<div class='mask'></div>");
184 $mask.after("<span class='tickeroverlay-left'> </span><span class='tickeroverlay-right'> </span>")
185 var $tickercontainer = $strip.parent().wrap("<div class='tickercontainer'></div>");
186
187 var started = initalize($strip);
188
189 if (settings.rssurl){
190 updaterss(settings.rssurl,settings.type,$strip);
191 if (settings.rssfrequency>0){
192 window.setInterval(function(){updaterss(settings.rssurl,settings.type,$strip);},settings.rssfrequency*1000*60);
193 }
194 }
195
196 if (cssTransitionsSupported){
197 //fix for firefox not animating default transitions
198 $strip.css('transition-duration','0s').css(settings.direction, '0');
199
200 if (started){
201 //if list has items and set up start scrolling
202 css3Scroll($strip,false);
203 }
204 //started or not still bind on the transition end event so it works after update
205 $strip.on('transitionend webkitTransitionEnd oTransitionEnd otransitionend', function(event) {
206 if (!$strip.is(event.target)) {
207 return false;
208 }
209 css3Scroll($(this),true);
210 });
211 } else {
212 if (started){
213 //if list has items and set up start scrolling
214 scrollitems($(this));
215 }
216 }
217
218 if (settings.hoverpause){
219 $strip.hover(function(){
220 if (cssTransitionsSupported){
221 var currentPosition = $(this).css(settings.direction);
222 $(this).css('transition-duration','0s').css(settings.direction,currentPosition);
223 } else
224 jQuery(this).stop();
225 },
226 function(){
227 if (jQuery(this).data('settings').moving){
228 if (cssTransitionsSupported){
229 css3Scroll($(this),false);
230 // $(this).css("-webkit-animation-play-state", "running");
231 } else {
232 //usual continue stuff
233 scrollitems($strip);
234 }
235 }
236 });
237 }
238 });
239 },
240 stop : function( ) {
241 var settings = $(this).data('settings');
242 if (settings.moving){
243 settings.moving = false;
244 return this.each(function(){
245 if (cssTransitionsSupported){
246 var currentPosition = $(this).css(settings.direction);
247 $(this).css('transition-duration','0s').css(settings.direction,currentPosition);
248 } else
249 $(this).stop();
250 });
251 }
252 },
253 cont : function( ) {
254 var settings = $(this).data('settings')
255 if (!settings.moving){
256 settings.moving = true;
257 return this.each(function(){
258 if (cssTransitionsSupported){
259 css3Scroll($(this),false);
260 } else {
261 scrollitems($(this));
262 }
263 });
264 }
265 },
266 update : function( list, type, insert, remove) {
267 type = type || "reset";
268 if (typeof insert === 'undefined')
269 insert = true;
270 if (typeof remove === 'undefined')
271 remove = false;
272 if( typeof list === 'string' ) {
273 list = $(list);
274 }
275 var $strip = $(this);
276 $strip.webTicker('stop');
277 var settings = $(this).data('settings');
278 if (type == 'reset'){
279 //this does a 'restart of the ticker'
280 $strip.html(list);
281 $strip.css(settings.direction, '0');
282 initalize($strip);
283 } else if (type == 'swap'){
284 if (window.console) {
285 console.log('trying to update');
286 }
287 if ($strip.children('li').length < 1){
288 //there were no items treat as if new
289 $strip.html(list);
290 $strip.css(settings.direction, '0');
291 initalize($strip);
292 } else {
293 // should the update be a 'hot-swap' or use replacement for IDs (in which case remove new ones)
294 $strip.children('li').addClass('old');
295 for (var i = 0; i < list.length; i++) {
296 id = $(list[i]).data('update');
297 match = $strip.find('[data-update="'+id+'"]');//should try find the id or data-attribute.
298 if (match.length < 1){
299 if (insert){
300 //we need to move this item into the dom
301 if ($strip.find('.ticker-spacer:first-child').length == 0 && $strip.find('.ticker-spacer').length > 0){
302 $strip.children('li.ticker-spacer').before(list[i]);
303 }
304 else {
305 $strip.append(list[i]);
306 }
307 }
308 } else $strip.find('[data-update="'+id+'"]').replaceWith(list[i]);;
309 };
310 $strip.children('li.webticker-init, li.ticker-spacer').removeClass('old');
311 if (remove)
312 $strip.children('li').remove('.old');
313 stripWidth = 0;
314 $strip.children('li').each(function(){
315 stripWidth += $(this).outerWidth( true );
316 });
317 $strip.width(stripWidth+200);
318 }
319 }
320
321 $strip.webTicker('cont');
322 }
323 };
324
325 $.fn.webTicker = function( method ) {
326
327 // Method calling logic
328 if ( methods[method] ) {
329 return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
330 } else if ( typeof method === 'object' || ! method ) {
331 return methods.init.apply( this, arguments );
332 } else {
333 $.error( 'Method ' + method + ' does not exist on jQuery.webTicker' );
334 }
335
336 };
337
338})( jQuery );