From 4fa4037cd6f85214acca59349a1c44552245848d Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Sat, 6 Nov 2010 12:17:18 +0100 Subject: [PATCH 01/20] Initial release of the jQuery UI Ticker. --- AUTHORS.txt | 1 + tests/static/ticker/default.html | 36 +++++ tests/unit/ticker/ticker.html | 48 ++++++ tests/unit/ticker/ticker_core.js | 11 ++ tests/unit/ticker/ticker_defaults.js | 15 ++ tests/unit/ticker/ticker_events.js | 8 + tests/unit/ticker/ticker_methods.js | 36 +++++ tests/unit/ticker/ticker_options.js | 8 + tests/unit/ticker/ticker_tickets.js | 8 + tests/visual/all.css | 5 + tests/visual/all.html | 15 ++ tests/visual/ticker/ticker.html | 33 ++++ .../visual/ticker/ticker_method_destroy.html | 30 ++++ .../visual/ticker/ticker_method_disable.html | 30 ++++ themes/base/jquery.ui.base.css | 1 + themes/base/jquery.ui.ticker.css | 11 ++ ui/jquery.ui.ticker.js | 148 ++++++++++++++++++ 17 files changed, 444 insertions(+) create mode 100644 tests/static/ticker/default.html create mode 100644 tests/unit/ticker/ticker.html create mode 100644 tests/unit/ticker/ticker_core.js create mode 100644 tests/unit/ticker/ticker_defaults.js create mode 100644 tests/unit/ticker/ticker_events.js create mode 100644 tests/unit/ticker/ticker_methods.js create mode 100644 tests/unit/ticker/ticker_options.js create mode 100644 tests/unit/ticker/ticker_tickets.js create mode 100644 tests/visual/ticker/ticker.html create mode 100644 tests/visual/ticker/ticker_method_destroy.html create mode 100644 tests/visual/ticker/ticker_method_disable.html create mode 100644 themes/base/jquery.ui.ticker.css create mode 100644 ui/jquery.ui.ticker.js diff --git a/AUTHORS.txt b/AUTHORS.txt index b2168655ee0..e4be5e747c4 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -28,3 +28,4 @@ Keith Wood (kbwood@virginbroadband.com.au) Maggie Costello Wachs Richard D. Worth (rdworth.org) Jörn Zaefferer (bassistance.de) +Kai Schlamp (schlamp@gmx.de) diff --git a/tests/static/ticker/default.html b/tests/static/ticker/default.html new file mode 100644 index 00000000000..bf8625a7c73 --- /dev/null +++ b/tests/static/ticker/default.html @@ -0,0 +1,36 @@ + + + + + Ticker Static Test : Default + + + + + + + + + + + + diff --git a/tests/unit/ticker/ticker.html b/tests/unit/ticker/ticker.html new file mode 100644 index 00000000000..7110982edd0 --- /dev/null +++ b/tests/unit/ticker/ticker.html @@ -0,0 +1,48 @@ + + + + + jQuery UI Ticker Test Suite + + + + + + + + + + + + + + + + + + + + + + + + +

jQuery UI Ticker Test Suite

+

+

+
    +
+ +
+ +
+ + + diff --git a/tests/unit/ticker/ticker_core.js b/tests/unit/ticker/ticker_core.js new file mode 100644 index 00000000000..e286be976a0 --- /dev/null +++ b/tests/unit/ticker/ticker_core.js @@ -0,0 +1,11 @@ +/* + * ticker_core.js + */ + +var el; + +(function($) { + +module("ticker: core"); + +})(jQuery); diff --git a/tests/unit/ticker/ticker_defaults.js b/tests/unit/ticker/ticker_defaults.js new file mode 100644 index 00000000000..5defc832717 --- /dev/null +++ b/tests/unit/ticker/ticker_defaults.js @@ -0,0 +1,15 @@ +/* + * ticker_defaults.js + */ + +var ticker_defaults = { + disabled: false, + initialTimeout: 4000, + mouseOnTimeout: 8000, + mouseOffTimeout: 4000, + slidingTime: 800, + fadeInTime: 1000, + next: null +}; + +commonWidgetTests('ticker', { defaults: ticker_defaults }); diff --git a/tests/unit/ticker/ticker_events.js b/tests/unit/ticker/ticker_events.js new file mode 100644 index 00000000000..fc17d5fe604 --- /dev/null +++ b/tests/unit/ticker/ticker_events.js @@ -0,0 +1,8 @@ +/* + * ticker_events.js + */ +(function($) { + +module("ticker: events"); + +})(jQuery); diff --git a/tests/unit/ticker/ticker_methods.js b/tests/unit/ticker/ticker_methods.js new file mode 100644 index 00000000000..a0db397e3ae --- /dev/null +++ b/tests/unit/ticker/ticker_methods.js @@ -0,0 +1,36 @@ +/* + * ticker_methods.js + */ +(function($) { + +module("ticker: methods"); + +test("init", function() { + $("").appendTo('body').ticker().remove(); + ok(true, '.ticker() called on element'); + + $([]).ticker().remove(); + ok(true, '.ticker() called on empty collection'); + + $('').ticker().remove(); + ok(true, '.ticker() called on disconnected DOMElement - never connected'); + + $('').appendTo('body').remove().ticker().remove(); + ok(true, '.ticker() called on disconnected DOMElement - removed'); + + var el = $('').ticker(); + var foo = el.ticker("option", "foo"); + el.remove(); + ok(true, 'arbitrary option getter after init'); + + $('').ticker().ticker("option", "foo", "bar").remove(); + ok(true, 'arbitrary option setter after init'); +}); + +test("destroy", function() { + var beforeHtml = $("#ticker").find("div").css("font-style", "normal").end().parent().html(); + var afterHtml = $("#ticker").ticker().ticker("destroy").parent().html(); + equal( afterHtml, beforeHtml ); +}); + +})(jQuery); diff --git a/tests/unit/ticker/ticker_options.js b/tests/unit/ticker/ticker_options.js new file mode 100644 index 00000000000..cc634a6852e --- /dev/null +++ b/tests/unit/ticker/ticker_options.js @@ -0,0 +1,8 @@ +/* + * ticker_options.js + */ +(function($) { + +module("ticker: options"); + +})(jQuery); diff --git a/tests/unit/ticker/ticker_tickets.js b/tests/unit/ticker/ticker_tickets.js new file mode 100644 index 00000000000..cb0105a2847 --- /dev/null +++ b/tests/unit/ticker/ticker_tickets.js @@ -0,0 +1,8 @@ +/* + * ticker_tickets.js + */ +(function($) { + +module("ticker: tickets"); + +})(jQuery); diff --git a/tests/visual/all.css b/tests/visual/all.css index d4b4805a1fb..8e44fa8aed2 100644 --- a/tests/visual/all.css +++ b/tests/visual/all.css @@ -82,3 +82,8 @@ li.plugin { #droppable .draggable { margin: 7px; } + +#ticker { + width: 200px; + margin: 10px 10px 0px 10px; +} diff --git a/tests/visual/all.html b/tests/visual/all.html index 6e800f344ae..b8e6283cf07 100644 --- a/tests/visual/all.html +++ b/tests/visual/all.html @@ -23,6 +23,7 @@ + @@ -183,6 +187,17 @@

Third

Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.
+
  • + Ticker + +
  • diff --git a/tests/visual/ticker/ticker.html b/tests/visual/ticker/ticker.html new file mode 100644 index 00000000000..5ade24529d9 --- /dev/null +++ b/tests/visual/ticker/ticker.html @@ -0,0 +1,33 @@ + + + + + Ticker Visual Test : Default + + + + + + + + + + + + + + diff --git a/tests/visual/ticker/ticker_method_destroy.html b/tests/visual/ticker/ticker_method_destroy.html new file mode 100644 index 00000000000..eff297e096d --- /dev/null +++ b/tests/visual/ticker/ticker_method_destroy.html @@ -0,0 +1,30 @@ + + + + + Ticker Visual Test : Ticker method destroy + + + + + + + + + + + + + + diff --git a/tests/visual/ticker/ticker_method_disable.html b/tests/visual/ticker/ticker_method_disable.html new file mode 100644 index 00000000000..5f2dd590ffc --- /dev/null +++ b/tests/visual/ticker/ticker_method_disable.html @@ -0,0 +1,30 @@ + + + + + Ticker Visual Test : Ticker method disable + + + + + + + + + + + + + + diff --git a/themes/base/jquery.ui.base.css b/themes/base/jquery.ui.base.css index 7634fb61e7c..2869e19aba7 100644 --- a/themes/base/jquery.ui.base.css +++ b/themes/base/jquery.ui.base.css @@ -19,3 +19,4 @@ @import url("jquery.ui.selectable.css"); @import url("jquery.ui.slider.css"); @import url("jquery.ui.tabs.css"); +@import url("jquery.ui.ticker.css"); diff --git a/themes/base/jquery.ui.ticker.css b/themes/base/jquery.ui.ticker.css new file mode 100644 index 00000000000..b96acc2e646 --- /dev/null +++ b/themes/base/jquery.ui.ticker.css @@ -0,0 +1,11 @@ +/* + * jQuery UI Ticker @VERSION + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Ticker#theming + */ +.ui-ticker { width: 100%; margin: 0px; padding: 0px; } +.ui-ticker .ui-ticker-content { display: block; font-size: 1em; padding: .5em .5em .5em .7em; margin-bottom: 1px; } diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js new file mode 100644 index 00000000000..b74fc080447 --- /dev/null +++ b/ui/jquery.ui.ticker.js @@ -0,0 +1,148 @@ +/* + * jQuery UI Ticker @VERSION + * + * Copyright 2010, AUTHORS.txt (http://jqueryui.com/about) + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + * + * http://docs.jquery.com/UI/Ticker + * + * Depends: + * jquery.ui.core.js + * jquery.ui.widget.js + */ +(function( $, undefined ) { + +$.widget( "ui.ticker", { + options: { + initialTimeout: 4000, + mouseOnTimeout: 8000, + mouseOffTimeout: 4000, + slidingTime: 800, + fadeInTime: 1000, + next: null + }, + + _create: function() { + var self = this, + options = self.options; + + self.speed = options.mouseOffTimeout; + + self.element + .addClass( "ui-ticker ui-widget ui-corner-all" ) + .bind( "mouseenter.ticker", function() { + if ( options.disabled ) { + return; + } + self.speed = options.mouseOnTimeout; + if (self.timeoutId !== undefined) { + window.clearTimeout(timeoutId); + self.timeoutId = window.setTimeout(function() { self.rotate(); }, self.speed); + } + }) + .bind( "mouseleave.ticker", function() { + if ( options.disabled ) { + return; + } + self.speed = options.mouseOffTimeout; + if (self.timeoutId !== undefined) { + window.clearTimeout(timeoutId); + self.timeoutId = window.setTimeout(function() { self.rotate(); }, self.speed); + } + }); + + self._addItemClasses(self.element.children( "li" )); + self._addItemBindings(self.element.children( "li" )); + }, + + _init: function() { + var self = this, + options = self.options; + + window.setTimeout(function() { self.rotate() }, options.initialTimeout); + }, + + destroy: function() { + this.element.unbind(".ticker"); + this.element.children( "li" ).unbind(".ticker"); + this.element.removeClass( "ui-ticker ui-widget ui-corner-all" ); + this._removeItemClasses(this.element.children( "li" )); + + return $.Widget.prototype.destroy.call( this ); + }, + + _addItemClasses: function(item) { + item.addClass( "ui-ticker-content ui-widget-content ui-helper-reset ui-state-default ui-corner-all" ) + }, + + _removeItemClasses: function(item) { + item.removeClass( "ui-ticker-content ui-widget-content ui-helper-reset ui-state-default ui-state-hover ui-state-focus ui-corner-all" ) + }, + + _addItemBindings: function(item) { + var options = this.options; + + item + .bind( "mouseenter.ticker", function() { + if ( options.disabled ) { + return; + } + $( this ).addClass( "ui-state-hover" ); + }) + .bind( "mouseleave.ticker", function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( "ui-state-hover" ); + }) + .bind( "focus.ticker", function() { + if ( options.disabled ) { + return; + } + $( this ).addClass( "ui-state-focus" ); + }) + .bind( "blur.ticker", function() { + if ( options.disabled ) { + return; + } + $( this ).removeClass( "ui-state-focus" ); + }); + }, + + rotate: function() { + var self = this, + options = self.options, + newItem, + lastItem; + + lastItem = lastItem = self.element.children().last().clone(); + self._removeItemClasses(lastItem); + + newItem = $( self.options.next(lastItem.get()) ); + + if (newItem !== null) { + self._addItemClasses(newItem); + self._addItemBindings(newItem); + newItem + .hide() + .prependTo(self.element) + .css('visibility', 'hidden') + .slideDown(options.slidingTime, function() { + $( this ).fadeTo(0, 0).css('visibility', 'visible').fadeTo(options.fadeInTime, 1); + }); + + self.element.children().last().slideUp(options.slidingTime, function() { + $( this ).remove(); + }); + } + + self.timeoutId = window.setTimeout(function() { self.rotate(); }, self.speed); + } +}); + +$.extend( $.ui.ticker, { + version: "@VERSION" +}); + +})( jQuery ); From 7528b3f07e42c9da5d1bbe428f94e15b8ee5fd81 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Sun, 7 Nov 2010 15:42:58 +0100 Subject: [PATCH 02/20] Active option. Stop and start method. More tests. --- tests/unit/ticker/ticker_defaults.js | 1 + tests/unit/ticker/ticker_methods.js | 69 ++++++++++++++++++++ ui/jquery.ui.ticker.js | 96 +++++++++++++++++----------- 3 files changed, 130 insertions(+), 36 deletions(-) diff --git a/tests/unit/ticker/ticker_defaults.js b/tests/unit/ticker/ticker_defaults.js index 5defc832717..60d2a52fd3d 100644 --- a/tests/unit/ticker/ticker_defaults.js +++ b/tests/unit/ticker/ticker_defaults.js @@ -4,6 +4,7 @@ var ticker_defaults = { disabled: false, + active: true, initialTimeout: 4000, mouseOnTimeout: 8000, mouseOffTimeout: 4000, diff --git a/tests/unit/ticker/ticker_methods.js b/tests/unit/ticker/ticker_methods.js index a0db397e3ae..91b44a58ccd 100644 --- a/tests/unit/ticker/ticker_methods.js +++ b/tests/unit/ticker/ticker_methods.js @@ -33,4 +33,73 @@ test("destroy", function() { equal( afterHtml, beforeHtml ); }); +test("initial stop", function() { + expect(0); + stop(); + + $("#ticker").ticker({ + initialTimeout: 100, + next: function(lastItem) { + ok(false, "ticker should not scroll after it was stopped"); + return lastItem; + } + }); + $("#ticker").ticker("stop"); + + setTimeout(function() { start(); }, 200); +}); + +test("stop after scroll", function() { + expect(1); + stop(); + + var counter = 0; + + $("#ticker").ticker({ + initialTimeout: 0, + mouseOnTimeout: 100, + mouseOffTimeout: 100, + slidingTime: 0, + fadeInTime: 0, + next: function(lastItem) { + if (counter == 0) { + ok(true, "ticker scrolled one time"); + $("#ticker").ticker("stop"); + counter++; + return lastItem; + } + else { + ok(false, "ticker should not scroll after it was stopped"); + return lastItem; + } + } + }); + + setTimeout(function() { start(); }, 300); +}); + +test("start", function() { + expect(1); + stop(); + + var started = false; + + $("#ticker").ticker({ + initialTimeout: 100, + mouseOnTimeout: 100, + mouseOffTimeout: 100, + slidingTime: 0, + fadeInTime: 0, + next: function(lastItem) { + if (started) { + ok(true, "ticker scrolled after it was started"); + $("#ticker").ticker("stop"); + } + } + }); + $("#ticker").ticker("stop"); + window.setTimeout(function() { started = true; $("#ticker").ticker("start"); }, 200); + window.setTimeout(function() { start(); }, 300); +}); + })(jQuery); diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index b74fc080447..6c5e290b37e 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -12,9 +12,12 @@ * jquery.ui.widget.js */ (function( $, undefined ) { + +var itemClasses = "ui-ticker-content ui-widget-content ui-helper-reset ui-state-default ui-corner-all"; $.widget( "ui.ticker", { options: { + active: true, initialTimeout: 4000, mouseOnTimeout: 8000, mouseOffTimeout: 4000, @@ -27,6 +30,8 @@ $.widget( "ui.ticker", { var self = this, options = self.options; + self.timeoutId = null; + self.speed = options.mouseOffTimeout; self.element @@ -36,9 +41,9 @@ $.widget( "ui.ticker", { return; } self.speed = options.mouseOnTimeout; - if (self.timeoutId !== undefined) { - window.clearTimeout(timeoutId); - self.timeoutId = window.setTimeout(function() { self.rotate(); }, self.speed); + if (options.active && self.timeoutId !== null) { + window.clearTimeout(self.timeoutId); + self.timeoutId = window.setTimeout(function() { self._scroll(); }, self.speed); } }) .bind( "mouseleave.ticker", function() { @@ -46,13 +51,13 @@ $.widget( "ui.ticker", { return; } self.speed = options.mouseOffTimeout; - if (self.timeoutId !== undefined) { - window.clearTimeout(timeoutId); - self.timeoutId = window.setTimeout(function() { self.rotate(); }, self.speed); + if (options.active && self.timeoutId !== null) { + window.clearTimeout(self.timeoutId); + self.timeoutId = window.setTimeout(function() { self._scroll(); }, self.speed); } }); - self._addItemClasses(self.element.children( "li" )); + self.element.children( "li" ).addClass(itemClasses); self._addItemBindings(self.element.children( "li" )); }, @@ -60,26 +65,20 @@ $.widget( "ui.ticker", { var self = this, options = self.options; - window.setTimeout(function() { self.rotate() }, options.initialTimeout); + if (options.active) { + self.timeoutId = window.setTimeout(function() { self._scroll() }, options.initialTimeout); + } }, destroy: function() { this.element.unbind(".ticker"); this.element.children( "li" ).unbind(".ticker"); this.element.removeClass( "ui-ticker ui-widget ui-corner-all" ); - this._removeItemClasses(this.element.children( "li" )); + this.element.children( "li" ).removeClass(itemClasses + " ui-state-hover ui-state-focus"); return $.Widget.prototype.destroy.call( this ); }, - _addItemClasses: function(item) { - item.addClass( "ui-ticker-content ui-widget-content ui-helper-reset ui-state-default ui-corner-all" ) - }, - - _removeItemClasses: function(item) { - item.removeClass( "ui-ticker-content ui-widget-content ui-helper-reset ui-state-default ui-state-hover ui-state-focus ui-corner-all" ) - }, - _addItemBindings: function(item) { var options = this.options; @@ -110,34 +109,59 @@ $.widget( "ui.ticker", { }); }, - rotate: function() { + _scroll: function() { var self = this, options = self.options, newItem, lastItem; - lastItem = lastItem = self.element.children().last().clone(); - self._removeItemClasses(lastItem); - - newItem = $( self.options.next(lastItem.get()) ); + lastItem = self.element.children().last().clone(); + lastItem.removeClass(itemClasses + " ui-state-hover ui-state-focus"); - if (newItem !== null) { - self._addItemClasses(newItem); - self._addItemBindings(newItem); - newItem - .hide() - .prependTo(self.element) - .css('visibility', 'hidden') - .slideDown(options.slidingTime, function() { - $( this ).fadeTo(0, 0).css('visibility', 'visible').fadeTo(options.fadeInTime, 1); - }); + if (self.options.next !== null) { + newItem = $( self.options.next(lastItem.get()) ); + + if (newItem.length > 0) { + newItem.addClass(itemClasses); + self._addItemBindings(newItem); + newItem + .hide() + .prependTo(self.element) + .css('visibility', 'hidden') + .slideDown(options.slidingTime, function() { + $( this ).fadeTo(0, 0).css('visibility', 'visible').fadeTo(options.fadeInTime, 1); + }); - self.element.children().last().slideUp(options.slidingTime, function() { - $( this ).remove(); - }); + self.element.children().last().slideUp(options.slidingTime, function() { + $( this ).remove(); + }); + } } - self.timeoutId = window.setTimeout(function() { self.rotate(); }, self.speed); + if (options.active) { + self.timeoutId = window.setTimeout(function() { self._scroll(); }, self.speed); + } + }, + + stop: function() { + var self = this, + options = self.options; + + options.active = false; + if (self.timeoutId !== null) { + window.clearTimeout(self.timeoutId); + self.timeoutId = null; + } + }, + + start: function() { + var self = this, + options = self.options; + + options.active = true; + if (self.timeoutId === null) { + self.timeoutId = window.setTimeout(function() { self._scroll(); }, self.speed); + } } }); From 425b13e2e74dedaf1bbf2bf7f98b7fac147f68e9 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Sun, 7 Nov 2010 19:20:56 +0100 Subject: [PATCH 03/20] beforeScroll, afterScroll and afterFade bindings. More tests. --- tests/unit/ticker/ticker_events.js | 62 ++++++++++++++ tests/unit/ticker/ticker_options.js | 128 ++++++++++++++++++++++++++++ ui/jquery.ui.ticker.js | 45 ++++++++-- 3 files changed, 228 insertions(+), 7 deletions(-) diff --git a/tests/unit/ticker/ticker_events.js b/tests/unit/ticker/ticker_events.js index fc17d5fe604..23ad5a52cae 100644 --- a/tests/unit/ticker/ticker_events.js +++ b/tests/unit/ticker/ticker_events.js @@ -5,4 +5,66 @@ module("ticker: events"); +test("beforeScroll", function() { + expect(4); + stop(); + + $("#ticker").ticker({ + initialTimeout: 0, + slidingTime: 0, + fadeInTime: 0, + next: function(lastItem) { return '
  • TestItem
  • '; }, + beforeScroll: function(event, ui) { + ok(true, 'before scrolling fires beforeScroll callback'); + equals($("#ticker li").length, 6, "list does have all items"); + equals($("#ticker li:first").text(), "Item1", "Item1 still on first position"); + equals($("#ticker li:last").text(), "Item6", "last item still in the list"); + } + }); + + window.setTimeout(function() { start(); }, 100); +}); + +test("afterScroll", function() { + expect(5); + stop(); + + $("#ticker").ticker({ + initialTimeout: 0, + slidingTime: 0, + fadeInTime: 10000, + next: function(lastItem) { return '
  • TestItem
  • '; }, + afterScroll: function(event, ui) { + ok(true, 'after scrolling fires afterScroll callback'); + equals($("#ticker li").length, 6, "list does have all items"); + equals($("#ticker li:first").text(), "TestItem", "TestItem is first list item"); + ok($("#ticker li:first").css("opacity") < 1, "TestItem is not fully visible yet"); + equals($("#ticker li:last").text(), "Item5", "Item5 is last list item"); + } + }); + + window.setTimeout(function() { start(); }, 100); +}); + +test("afterFade", function() { + expect(5); + stop(); + + $("#ticker").ticker({ + initialTimeout: 0, + slidingTime: 0, + fadeInTime: 100, + next: function(lastItem) { return '
  • TestItem
  • '; }, + afterFade: function(event, ui) { + ok(true, 'after fade fires afterFade callback'); + equals($("#ticker li").length, 6, "list does have all items"); + equals($("#ticker li:first").text(), "TestItem", "TestItem is first list item"); + ok($("#ticker li:first").css("opacity") == 1, "TestItem is fully visible"); + equals($("#ticker li:last").text(), "Item5", "Item5 is last list item"); + } + }); + + window.setTimeout(function() { start(); }, 200); +}); + })(jQuery); diff --git a/tests/unit/ticker/ticker_options.js b/tests/unit/ticker/ticker_options.js index cc634a6852e..a1cae58cff1 100644 --- a/tests/unit/ticker/ticker_options.js +++ b/tests/unit/ticker/ticker_options.js @@ -5,4 +5,132 @@ module("ticker: options"); +test("{initalTimout: 200}", function() { + expect(1); + stop(); + var nextCalled = false; + $("#ticker").ticker({ + initialTimeout: 200, + next: function(lastItem) { + nextCalled = true; + return lastItem; + } + }); + + window.setTimeout(function() { + if (nextCalled) { + ok(false, "next called in initial timeout"); + } + }, 100); + + window.setTimeout(function() { + if (nextCalled) { + ok(true, "next called after timeout"); + } + start(); + }, 200); +}); + +test("{initialTimeout: 200} after calling start method", function() { + expect(1); + stop(); + var nextCalled = false; + $("#ticker").ticker({ + initialTimeout: 200, + next: function(lastItem) { + nextCalled = true; + return lastItem; + } + }); + + $("#ticker").ticker("stop"); + $("#ticker").ticker("start"); + + window.setTimeout(function() { + if (nextCalled) { + ok(false, "next called in initial timeout"); + } + }, 100); + + window.setTimeout(function() { + if (nextCalled) { + ok(true, "next called after timeout"); + } + start(); + }, 200); +}); + +test("{mouseOffTimeout: 100}", function() { + expect(2); + stop(); + + var counter = 0; + + var nextCalled = false; + $("#ticker").ticker({ + initialTimeout: 0, + mouseOnTimeout: 10000, + mouseOffTimeout: 100, + next: function(lastItem) { + ok(true, "Next called (one time after init and one time afterwards"); + if (counter == 1) { + $("#ticker").ticker("stop"); + } + counter++; + return lastItem; + } + }); + + window.setTimeout(function() { start(); }, 200 ); +}); + +test("{mouseOnTimeout: 100}", function() { + expect(2); + stop(); + + var counter = 0; + + var nextCalled = false; + + $("#ticker").ticker({ + initialTimeout: 0, + mouseOnTimeout: 100, + mouseOffTimeout: 10000, + next: function(lastItem) { + ok(true, "Next called (one time after init and one time afterwards"); + if (counter == 1) { + $("#ticker").ticker("stop"); + } + counter++; + return lastItem; + } + }); + + $("#ticker").simulate("mouseover"); + window.setTimeout(function() { start(); }, 200 ); +}); + +test('{next: function() {return "TestItem"}}', function() { + expect(2); + stop(); + + var nextCalled = false; + + $("#ticker").ticker({ + initialTimeout: 0, + slidingTime: 0, + fadeInTime: 0, + mouseOffTimeout: 10000, + next: function(lastItem) { + return "
  • TestItem
  • "; + } + }); + + window.setTimeout(function() { + equals($("#ticker li:first").html(), "TestItem", "new item was added"); + equals($("#ticker li:last").html(), "Item5", "last item was removed"); + start(); + }, 100 ); +}); + })(jQuery); diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index 6c5e290b37e..123f059c55f 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -71,12 +71,18 @@ $.widget( "ui.ticker", { }, destroy: function() { - this.element.unbind(".ticker"); - this.element.children( "li" ).unbind(".ticker"); - this.element.removeClass( "ui-ticker ui-widget ui-corner-all" ); - this.element.children( "li" ).removeClass(itemClasses + " ui-state-hover ui-state-focus"); + var self = this; + + self.element.unbind(".ticker"); + self.element.children( "li" ).unbind(".ticker"); + self.element.removeClass( "ui-ticker ui-widget ui-corner-all" ); + self.element.children( "li" ).removeClass(itemClasses + " ui-state-hover ui-state-focus"); + if (self.timeoutId !== null) { + window.clearTimeout(self.timeoutId); + self.timeoutId = null; + } - return $.Widget.prototype.destroy.call( this ); + return $.Widget.prototype.destroy.call( self ); }, _addItemBindings: function(item) { @@ -115,6 +121,10 @@ $.widget( "ui.ticker", { newItem, lastItem; + if (false === self._trigger('beforeScroll')) { + return; + } + lastItem = self.element.children().last().clone(); lastItem.removeClass(itemClasses + " ui-state-hover ui-state-focus"); @@ -129,11 +139,17 @@ $.widget( "ui.ticker", { .prependTo(self.element) .css('visibility', 'hidden') .slideDown(options.slidingTime, function() { - $( this ).fadeTo(0, 0).css('visibility', 'visible').fadeTo(options.fadeInTime, 1); + $( this ) + .fadeTo(0, 0) + .css('visibility', 'visible') + .fadeTo(options.fadeInTime, 1, function() { + self._trigger('afterFade'); + }); }); self.element.children().last().slideUp(options.slidingTime, function() { $( this ).remove(); + self._trigger('afterScroll'); }); } } @@ -143,6 +159,21 @@ $.widget( "ui.ticker", { } }, + _setOption: function( key, value ) { + $.Widget.prototype._setOption.apply( this, arguments ); + + switch (key) { + case "active": + if (value) { + this.start(); + } + else { + this.stop(); + } + break; + } + }, + stop: function() { var self = this, options = self.options; @@ -160,7 +191,7 @@ $.widget( "ui.ticker", { options.active = true; if (self.timeoutId === null) { - self.timeoutId = window.setTimeout(function() { self._scroll(); }, self.speed); + self.timeoutId = window.setTimeout(function() { self._scroll(); }, options.initialTimeout); } } }); From 37354da4dbc0a9dff6d3912799408fc05ba4ed57 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Sun, 7 Nov 2010 19:25:44 +0100 Subject: [PATCH 04/20] Renamed fadeInTime to fadeTime. --- tests/unit/ticker/ticker_defaults.js | 2 +- tests/unit/ticker/ticker_events.js | 6 +++--- tests/unit/ticker/ticker_methods.js | 4 ++-- tests/unit/ticker/ticker_options.js | 2 +- ui/jquery.ui.ticker.js | 4 ++-- 5 files changed, 9 insertions(+), 9 deletions(-) diff --git a/tests/unit/ticker/ticker_defaults.js b/tests/unit/ticker/ticker_defaults.js index 60d2a52fd3d..470c62d38ca 100644 --- a/tests/unit/ticker/ticker_defaults.js +++ b/tests/unit/ticker/ticker_defaults.js @@ -9,7 +9,7 @@ var ticker_defaults = { mouseOnTimeout: 8000, mouseOffTimeout: 4000, slidingTime: 800, - fadeInTime: 1000, + fadeTime: 1000, next: null }; diff --git a/tests/unit/ticker/ticker_events.js b/tests/unit/ticker/ticker_events.js index 23ad5a52cae..89494860557 100644 --- a/tests/unit/ticker/ticker_events.js +++ b/tests/unit/ticker/ticker_events.js @@ -12,7 +12,7 @@ test("beforeScroll", function() { $("#ticker").ticker({ initialTimeout: 0, slidingTime: 0, - fadeInTime: 0, + fadeTime: 0, next: function(lastItem) { return '
  • TestItem
  • '; }, beforeScroll: function(event, ui) { ok(true, 'before scrolling fires beforeScroll callback'); @@ -32,7 +32,7 @@ test("afterScroll", function() { $("#ticker").ticker({ initialTimeout: 0, slidingTime: 0, - fadeInTime: 10000, + fadeTime: 10000, next: function(lastItem) { return '
  • TestItem
  • '; }, afterScroll: function(event, ui) { ok(true, 'after scrolling fires afterScroll callback'); @@ -53,7 +53,7 @@ test("afterFade", function() { $("#ticker").ticker({ initialTimeout: 0, slidingTime: 0, - fadeInTime: 100, + fadeTime: 100, next: function(lastItem) { return '
  • TestItem
  • '; }, afterFade: function(event, ui) { ok(true, 'after fade fires afterFade callback'); diff --git a/tests/unit/ticker/ticker_methods.js b/tests/unit/ticker/ticker_methods.js index 91b44a58ccd..de802c209b7 100644 --- a/tests/unit/ticker/ticker_methods.js +++ b/tests/unit/ticker/ticker_methods.js @@ -60,7 +60,7 @@ test("stop after scroll", function() { mouseOnTimeout: 100, mouseOffTimeout: 100, slidingTime: 0, - fadeInTime: 0, + fadeTime: 0, next: function(lastItem) { if (counter == 0) { ok(true, "ticker scrolled one time"); @@ -89,7 +89,7 @@ test("start", function() { mouseOnTimeout: 100, mouseOffTimeout: 100, slidingTime: 0, - fadeInTime: 0, + fadeTime: 0, next: function(lastItem) { if (started) { ok(true, "ticker scrolled after it was started"); diff --git a/tests/unit/ticker/ticker_options.js b/tests/unit/ticker/ticker_options.js index a1cae58cff1..1215d243aa5 100644 --- a/tests/unit/ticker/ticker_options.js +++ b/tests/unit/ticker/ticker_options.js @@ -119,7 +119,7 @@ test('{next: function() {return "TestItem"}}', function() { $("#ticker").ticker({ initialTimeout: 0, slidingTime: 0, - fadeInTime: 0, + fadeTime: 0, mouseOffTimeout: 10000, next: function(lastItem) { return "
  • TestItem
  • "; diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index 123f059c55f..c4ec4ad1e31 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -22,7 +22,7 @@ $.widget( "ui.ticker", { mouseOnTimeout: 8000, mouseOffTimeout: 4000, slidingTime: 800, - fadeInTime: 1000, + fadeTime: 1000, next: null }, @@ -142,7 +142,7 @@ $.widget( "ui.ticker", { $( this ) .fadeTo(0, 0) .css('visibility', 'visible') - .fadeTo(options.fadeInTime, 1, function() { + .fadeTo(options.fadeTime, 1, function() { self._trigger('afterFade'); }); }); From e91d8bb1fea3f0a6772fdff4936e150fb14a1f78 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 9 Nov 2010 10:36:07 +0100 Subject: [PATCH 05/20] Fixed a bug when nextItem returned null. Renamed next to nextItem. Renamed slidingTime to scrollTime. More tests. --- tests/unit/ticker/ticker_core.js | 20 ++++++++++++ tests/unit/ticker/ticker_defaults.js | 4 +-- tests/unit/ticker/ticker_events.js | 48 ++++++++++++++++++++++++---- tests/unit/ticker/ticker_methods.js | 12 +++---- tests/unit/ticker/ticker_options.js | 16 +++++----- tests/visual/all.html | 2 +- tests/visual/ticker/ticker.html | 2 +- ui/jquery.ui.ticker.js | 20 ++++++------ 8 files changed, 90 insertions(+), 34 deletions(-) diff --git a/tests/unit/ticker/ticker_core.js b/tests/unit/ticker/ticker_core.js index e286be976a0..35fa673b7ff 100644 --- a/tests/unit/ticker/ticker_core.js +++ b/tests/unit/ticker/ticker_core.js @@ -8,4 +8,24 @@ var el; module("ticker: core"); +test("nextItem returns null", function() { + expect(2); + stop(); + + $("#ticker").ticker({ + initialTimeout: 0, + scrollTime: 0, + fadeTime: 0, + nextItem: function(lastItem) { + ok(true, "nextItem is called") + return null; + } + }); + + window.setTimeout(function() { + equals($("#ticker li:first").text(), "Item1", "ticker has not scrolled"); + start(); + }, 100); +}); + })(jQuery); diff --git a/tests/unit/ticker/ticker_defaults.js b/tests/unit/ticker/ticker_defaults.js index 470c62d38ca..2bb157fb00d 100644 --- a/tests/unit/ticker/ticker_defaults.js +++ b/tests/unit/ticker/ticker_defaults.js @@ -8,9 +8,9 @@ var ticker_defaults = { initialTimeout: 4000, mouseOnTimeout: 8000, mouseOffTimeout: 4000, - slidingTime: 800, + scrollTime: 800, fadeTime: 1000, - next: null + nextItem: null }; commonWidgetTests('ticker', { defaults: ticker_defaults }); diff --git a/tests/unit/ticker/ticker_events.js b/tests/unit/ticker/ticker_events.js index 89494860557..0fe4de7c1ae 100644 --- a/tests/unit/ticker/ticker_events.js +++ b/tests/unit/ticker/ticker_events.js @@ -11,9 +11,9 @@ test("beforeScroll", function() { $("#ticker").ticker({ initialTimeout: 0, - slidingTime: 0, + scrollTime: 0, fadeTime: 0, - next: function(lastItem) { return '
  • TestItem
  • '; }, + nextItem: function(lastItem) { return $('
  • TestItem
  • '); }, beforeScroll: function(event, ui) { ok(true, 'before scrolling fires beforeScroll callback'); equals($("#ticker li").length, 6, "list does have all items"); @@ -31,9 +31,9 @@ test("afterScroll", function() { $("#ticker").ticker({ initialTimeout: 0, - slidingTime: 0, + scrollTime: 0, fadeTime: 10000, - next: function(lastItem) { return '
  • TestItem
  • '; }, + nextItem: function(lastItem) { return $('
  • TestItem
  • '); }, afterScroll: function(event, ui) { ok(true, 'after scrolling fires afterScroll callback'); equals($("#ticker li").length, 6, "list does have all items"); @@ -52,9 +52,9 @@ test("afterFade", function() { $("#ticker").ticker({ initialTimeout: 0, - slidingTime: 0, + scrollTime: 0, fadeTime: 100, - next: function(lastItem) { return '
  • TestItem
  • '; }, + nextItem: function(lastItem) { return $('
  • TestItem
  • '); }, afterFade: function(event, ui) { ok(true, 'after fade fires afterFade callback'); equals($("#ticker li").length, 6, "list does have all items"); @@ -67,4 +67,40 @@ test("afterFade", function() { window.setTimeout(function() { start(); }, 200); }); +test("correct order of nextItem call and events", function() { + expect(4); + stop(); + + var counter = 0; + + $("#ticker").ticker({ + initialTimeout: 0, + scrollTime: 50, + fadeTime: 50, + nextItem: function(lastItem) { + if (counter == 0) { + ok(true, "nextItem was called first") + } + return $('
  • TestItem
  • '); + }, + beforeScroll: function(event, ui) { + if (counter == 0) { + ok(true, "beforeScroll was called second") + } + }, + afterScroll: function(event, ui) { + if (counter == 0) { + ok(true, "afterScroll was called third") + } + }, + afterFade: function(event, ui) { + if (counter == 0) { + ok(true, "afterFade was called fourth") + } + } + }); + + window.setTimeout(function() { start(); }, 200); +}); + })(jQuery); diff --git a/tests/unit/ticker/ticker_methods.js b/tests/unit/ticker/ticker_methods.js index de802c209b7..c5820c87125 100644 --- a/tests/unit/ticker/ticker_methods.js +++ b/tests/unit/ticker/ticker_methods.js @@ -39,7 +39,7 @@ test("initial stop", function() { $("#ticker").ticker({ initialTimeout: 100, - next: function(lastItem) { + nextItem: function(lastItem) { ok(false, "ticker should not scroll after it was stopped"); return lastItem; } @@ -59,9 +59,9 @@ test("stop after scroll", function() { initialTimeout: 0, mouseOnTimeout: 100, mouseOffTimeout: 100, - slidingTime: 0, + scrollTime: 0, fadeTime: 0, - next: function(lastItem) { + nextItem: function(lastItem) { if (counter == 0) { ok(true, "ticker scrolled one time"); $("#ticker").ticker("stop"); @@ -88,9 +88,9 @@ test("start", function() { initialTimeout: 100, mouseOnTimeout: 100, mouseOffTimeout: 100, - slidingTime: 0, + scrollTime: 0, fadeTime: 0, - next: function(lastItem) { + nextItem: function(lastItem) { if (started) { ok(true, "ticker scrolled after it was started"); $("#ticker").ticker("stop"); @@ -99,7 +99,7 @@ test("start", function() { }); $("#ticker").ticker("stop"); window.setTimeout(function() { started = true; $("#ticker").ticker("start"); }, 200); - window.setTimeout(function() { start(); }, 300); + window.setTimeout(function() { start(); }, 500); }); })(jQuery); diff --git a/tests/unit/ticker/ticker_options.js b/tests/unit/ticker/ticker_options.js index 1215d243aa5..730576daa4b 100644 --- a/tests/unit/ticker/ticker_options.js +++ b/tests/unit/ticker/ticker_options.js @@ -11,7 +11,7 @@ test("{initalTimout: 200}", function() { var nextCalled = false; $("#ticker").ticker({ initialTimeout: 200, - next: function(lastItem) { + nextItem: function(lastItem) { nextCalled = true; return lastItem; } @@ -37,7 +37,7 @@ test("{initialTimeout: 200} after calling start method", function() { var nextCalled = false; $("#ticker").ticker({ initialTimeout: 200, - next: function(lastItem) { + nextItem: function(lastItem) { nextCalled = true; return lastItem; } @@ -71,7 +71,7 @@ test("{mouseOffTimeout: 100}", function() { initialTimeout: 0, mouseOnTimeout: 10000, mouseOffTimeout: 100, - next: function(lastItem) { + nextItem: function(lastItem) { ok(true, "Next called (one time after init and one time afterwards"); if (counter == 1) { $("#ticker").ticker("stop"); @@ -96,7 +96,7 @@ test("{mouseOnTimeout: 100}", function() { initialTimeout: 0, mouseOnTimeout: 100, mouseOffTimeout: 10000, - next: function(lastItem) { + nextItem: function(lastItem) { ok(true, "Next called (one time after init and one time afterwards"); if (counter == 1) { $("#ticker").ticker("stop"); @@ -110,7 +110,7 @@ test("{mouseOnTimeout: 100}", function() { window.setTimeout(function() { start(); }, 200 ); }); -test('{next: function() {return "TestItem"}}', function() { +test('{nextItem: function() {return $("TestItem")}}', function() { expect(2); stop(); @@ -118,11 +118,11 @@ test('{next: function() {return "TestItem"}}', function() { $("#ticker").ticker({ initialTimeout: 0, - slidingTime: 0, + scrollTime: 0, fadeTime: 0, mouseOffTimeout: 10000, - next: function(lastItem) { - return "
  • TestItem
  • "; + nextItem: function(lastItem) { + return $("
  • TestItem
  • "); } }); diff --git a/tests/visual/all.html b/tests/visual/all.html index b8e6283cf07..4d6cd00c54c 100644 --- a/tests/visual/all.html +++ b/tests/visual/all.html @@ -51,7 +51,7 @@ $("#sortable").sortable(); $("#tabs").tabs(); $("#ticker").ticker({ - next: function(lastItem) { return lastItem; } + nextItem: function(lastItem) { return lastItem; } }); }); diff --git a/tests/visual/ticker/ticker.html b/tests/visual/ticker/ticker.html index 5ade24529d9..f9bfed7a743 100644 --- a/tests/visual/ticker/ticker.html +++ b/tests/visual/ticker/ticker.html @@ -13,7 +13,7 @@ $(function() { var i = 0; $("#ticker").ticker({ - next: function(lastItem) { return lastItem; } + nextItem: function(lastItem) { return lastItem; } }); }) diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index c4ec4ad1e31..0616481d0d4 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -21,9 +21,9 @@ $.widget( "ui.ticker", { initialTimeout: 4000, mouseOnTimeout: 8000, mouseOffTimeout: 4000, - slidingTime: 800, + scrollTime: 800, fadeTime: 1000, - next: null + nextItem: null }, _create: function() { @@ -121,24 +121,24 @@ $.widget( "ui.ticker", { newItem, lastItem; - if (false === self._trigger('beforeScroll')) { - return; - } - lastItem = self.element.children().last().clone(); lastItem.removeClass(itemClasses + " ui-state-hover ui-state-focus"); if (self.options.next !== null) { - newItem = $( self.options.next(lastItem.get()) ); + newItem = self.options.nextItem(lastItem); - if (newItem.length > 0) { + if (newItem != null && newItem.length > 0) { + if (false === self._trigger('beforeScroll')) { + return; + } + newItem.addClass(itemClasses); self._addItemBindings(newItem); newItem .hide() .prependTo(self.element) .css('visibility', 'hidden') - .slideDown(options.slidingTime, function() { + .slideDown(options.scrollTime, function() { $( this ) .fadeTo(0, 0) .css('visibility', 'visible') @@ -147,7 +147,7 @@ $.widget( "ui.ticker", { }); }); - self.element.children().last().slideUp(options.slidingTime, function() { + self.element.children().last().slideUp(options.scrollTime, function() { $( this ).remove(); self._trigger('afterScroll'); }); From c467e0f592b9e4cc9430e3fe00580beb9a0b0fac Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 9 Nov 2010 11:58:55 +0100 Subject: [PATCH 06/20] Better visualization by using overflow: hidden instead of synchronized slidings. --- themes/base/jquery.ui.ticker.css | 2 +- ui/jquery.ui.ticker.js | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/themes/base/jquery.ui.ticker.css b/themes/base/jquery.ui.ticker.css index b96acc2e646..0affeb4505a 100644 --- a/themes/base/jquery.ui.ticker.css +++ b/themes/base/jquery.ui.ticker.css @@ -7,5 +7,5 @@ * * http://docs.jquery.com/UI/Ticker#theming */ -.ui-ticker { width: 100%; margin: 0px; padding: 0px; } +.ui-ticker { width: 100%; margin: 0px; padding: 0px; overflow: hidden } .ui-ticker .ui-ticker-content { display: block; font-size: 1em; padding: .5em .5em .5em .7em; margin-bottom: 1px; } diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index 0616481d0d4..1503019e23c 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -59,6 +59,8 @@ $.widget( "ui.ticker", { self.element.children( "li" ).addClass(itemClasses); self._addItemBindings(self.element.children( "li" )); + + self.element.height(self.element.height()); }, _init: function() { @@ -145,12 +147,9 @@ $.widget( "ui.ticker", { .fadeTo(options.fadeTime, 1, function() { self._trigger('afterFade'); }); + self.element.children().last().remove(); + self._trigger('afterScroll'); }); - - self.element.children().last().slideUp(options.scrollTime, function() { - $( this ).remove(); - self._trigger('afterScroll'); - }); } } From 0eb46622680233543ccca41bae5abf29e543a8a6 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 9 Nov 2010 14:13:52 +0100 Subject: [PATCH 07/20] beforeScroll is not allowed to stop the ticker anymore as nextItem can also do that. --- ui/jquery.ui.ticker.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index 1503019e23c..ecaa8d94e1d 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -130,9 +130,7 @@ $.widget( "ui.ticker", { newItem = self.options.nextItem(lastItem); if (newItem != null && newItem.length > 0) { - if (false === self._trigger('beforeScroll')) { - return; - } + self._trigger('beforeScroll'); newItem.addClass(itemClasses); self._addItemBindings(newItem); From 544e95e062e11007b2919568e53a06be8fa15851 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 9 Nov 2010 14:14:57 +0100 Subject: [PATCH 08/20] Some little adjustments so tests have enough time. --- tests/unit/ticker/ticker_options.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/unit/ticker/ticker_options.js b/tests/unit/ticker/ticker_options.js index 730576daa4b..0bf101c1a60 100644 --- a/tests/unit/ticker/ticker_options.js +++ b/tests/unit/ticker/ticker_options.js @@ -81,7 +81,7 @@ test("{mouseOffTimeout: 100}", function() { } }); - window.setTimeout(function() { start(); }, 200 ); + window.setTimeout(function() { start(); }, 300 ); }); test("{mouseOnTimeout: 100}", function() { @@ -107,7 +107,7 @@ test("{mouseOnTimeout: 100}", function() { }); $("#ticker").simulate("mouseover"); - window.setTimeout(function() { start(); }, 200 ); + window.setTimeout(function() { start(); }, 300 ); }); test('{nextItem: function() {return $("TestItem")}}', function() { From 01795326de3b756434b457d8489bc42b82a6c7f0 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 9 Nov 2010 14:26:04 +0100 Subject: [PATCH 09/20] The added style (by setting the height) is now removed again when destroying the ticker. --- ui/jquery.ui.ticker.js | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index ecaa8d94e1d..5913a2f1b8f 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -60,6 +60,13 @@ $.widget( "ui.ticker", { self.element.children( "li" ).addClass(itemClasses); self._addItemBindings(self.element.children( "li" )); + var style = self.element.attr("style"); + if (style === undefined || style === null) { + self.originalStyle = null; + } + else { + self.originalStyle = self.element.attr("style") + } self.element.height(self.element.height()); }, @@ -74,14 +81,22 @@ $.widget( "ui.ticker", { destroy: function() { var self = this; + + if (self.timeoutId !== null) { + window.clearTimeout(self.timeoutId); + self.timeoutId = null; + } self.element.unbind(".ticker"); self.element.children( "li" ).unbind(".ticker"); self.element.removeClass( "ui-ticker ui-widget ui-corner-all" ); self.element.children( "li" ).removeClass(itemClasses + " ui-state-hover ui-state-focus"); - if (self.timeoutId !== null) { - window.clearTimeout(self.timeoutId); - self.timeoutId = null; + + if (self.originalStyle === null) { + self.element.removeAttr("style"); + } + else { + self.element.attr("style", self.originalStyle); } return $.Widget.prototype.destroy.call( self ); From 1264a98876b785a6b5a7af0eca62606cc63d2658 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 9 Nov 2010 20:54:38 +0100 Subject: [PATCH 10/20] Provide the data and bindings also for the clone, so that users can access them in the nextItem method. --- ui/jquery.ui.ticker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index 5913a2f1b8f..9ea24a8bf2d 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -138,7 +138,7 @@ $.widget( "ui.ticker", { newItem, lastItem; - lastItem = self.element.children().last().clone(); + lastItem = self.element.children().last().clone(true); lastItem.removeClass(itemClasses + " ui-state-hover ui-state-focus"); if (self.options.next !== null) { From b6a4cca79a554a045e848fc8e983c04ff1ed12e0 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Wed, 10 Nov 2010 00:00:35 +0100 Subject: [PATCH 11/20] Retain data and bindings on cloned last item. Some text adjustments as ticker is not very accurate. --- tests/unit/ticker/ticker_core.js | 23 +++++++++++++++++++++++ tests/unit/ticker/ticker_events.js | 2 +- tests/unit/ticker/ticker_methods.js | 14 +++++++------- tests/unit/ticker/ticker_options.js | 4 ++-- 4 files changed, 33 insertions(+), 10 deletions(-) diff --git a/tests/unit/ticker/ticker_core.js b/tests/unit/ticker/ticker_core.js index 35fa673b7ff..4d501a79472 100644 --- a/tests/unit/ticker/ticker_core.js +++ b/tests/unit/ticker/ticker_core.js @@ -28,4 +28,27 @@ test("nextItem returns null", function() { }, 100); }); +test("last item clone retains data and bindings", function() { + expect(3); + stop(); + + $("#ticker li:last") + .data("test", "123") + .bind("click", function() {}); + + $("#ticker").ticker({ + initialTimeout: 0, + scrollTime: 0, + fadeTime: 0, + nextItem: function(lastItem) { + ok(true, "nextItem is called"); + equals(lastItem.data("test"), "123", "last item clone retains data"); + ok(lastItem.data("events") != null, "last item clone retains events"); + return null; + } + }); + + window.setTimeout(function() { start(); }, 200); +}); + })(jQuery); diff --git a/tests/unit/ticker/ticker_events.js b/tests/unit/ticker/ticker_events.js index 0fe4de7c1ae..2ef682e0f43 100644 --- a/tests/unit/ticker/ticker_events.js +++ b/tests/unit/ticker/ticker_events.js @@ -64,7 +64,7 @@ test("afterFade", function() { } }); - window.setTimeout(function() { start(); }, 200); + window.setTimeout(function() { start(); }, 300); }); test("correct order of nextItem call and events", function() { diff --git a/tests/unit/ticker/ticker_methods.js b/tests/unit/ticker/ticker_methods.js index c5820c87125..21d4edda38c 100644 --- a/tests/unit/ticker/ticker_methods.js +++ b/tests/unit/ticker/ticker_methods.js @@ -85,21 +85,21 @@ test("start", function() { var started = false; $("#ticker").ticker({ - initialTimeout: 100, - mouseOnTimeout: 100, - mouseOffTimeout: 100, - scrollTime: 0, - fadeTime: 0, + active: false, + initialTimeout: 0, nextItem: function(lastItem) { if (started) { ok(true, "ticker scrolled after it was started"); $("#ticker").ticker("stop"); } + else { + ok(false, "ticker scrolled without being started"); + } + } }); - $("#ticker").ticker("stop"); window.setTimeout(function() { started = true; $("#ticker").ticker("start"); }, 200); - window.setTimeout(function() { start(); }, 500); + window.setTimeout(function() { start(); }, 600); }); })(jQuery); diff --git a/tests/unit/ticker/ticker_options.js b/tests/unit/ticker/ticker_options.js index 0bf101c1a60..8be103670a9 100644 --- a/tests/unit/ticker/ticker_options.js +++ b/tests/unit/ticker/ticker_options.js @@ -81,7 +81,7 @@ test("{mouseOffTimeout: 100}", function() { } }); - window.setTimeout(function() { start(); }, 300 ); + window.setTimeout(function() { start(); }, 400 ); }); test("{mouseOnTimeout: 100}", function() { @@ -107,7 +107,7 @@ test("{mouseOnTimeout: 100}", function() { }); $("#ticker").simulate("mouseover"); - window.setTimeout(function() { start(); }, 300 ); + window.setTimeout(function() { start(); }, 400 ); }); test('{nextItem: function() {return $("TestItem")}}', function() { From 392ebb5c693620c52386a8a2ecbeaed321502af0 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Fri, 3 Dec 2010 15:55:58 -0800 Subject: [PATCH 12/20] Some documentation. --- README.md | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 5c7d79a1335..a52aeb89eff 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,39 @@ [jQuery UI](http://jqueryui.com/) - Interactions and Widgets for the web ================================ -jQuery UI provides interactions like Drag and Drop and widgets like Autocomplete, Tabs and Slider and makes these as easy to use as jQuery itself. +This fork of jQuery UI includes our brand new Ticker. We also have a [live demo](http://medihack.github.com/tickerdemo/) with some customized style sheets (for having a similar look like Twitter). -If you want to use jQuery UI, go to [jqueryui.com](http://jqueryui.com) to get started. Or visit the [Using jQuery UI Forum](http://forum.jquery.com/using-jquery-ui) for discussions and questions. +The Ticker in its raw form is fully compatible with the jQuery UI Theming framework. It is also quite flexible and well tested. -If you are interested in helping developing jQuery UI, you are in the right place. -To discuss development with team members and the community, visit the [Developing jQuery UI Forum](http://forum.jquery.com/developing-jquery-ui). +There are several options to easily customize the visualization: + + $("#ticker").ticker({ // #ticker is the id of an
      element that contains the
    • ticker elements + initialTimeout: 2000, // the initial timeout to start the ticker after the site was loaded (in ms) + mouseOnTimeout: 6000, // the timeout before the next item shows up when the mouse pointer is over the ticker + mouseOffTimeout: 4000, // the timeout before the next item shows up when the mouse pointer is somewhere else + scrollTime: 1200, // the times it takes to scroll down the item list + fadeTime: 1000, // the time it takes to fade in the next item at the top of the item list + nextItem: function(lastItem) { // this function provides a clone of the last item on the list that will be removed next + return $(lastItem); // the item that should be added next to the ticker (should be a jQuery
    • item) + } // in this case the last item is directly added again to the top of the ticker + }); + +There are also several events fired: +beforeScroll // directly before the ticker scrolls +afterScroll // directly after the ticker scrolled +afterFade // directly after the new item was faded in + +To bind to an event (the common jQuery UI way): + + $("#ticker").ticker({ + nextItem: function(lastItem) { return $('
    • TestItem
    • '); }, + beforeScroll: function(event, ui) { // just do what you like to do } + }); + +We also provide some methods: +stop // stop the ticker immediately (respectively after a current on going scrolling/fading was finished) +start // start the ticker again + +To call those methods (the common jQuery UI way): + + $("#ticker").ticker("stop"); \ No newline at end of file From be3506b55b9b3de22fa296235ed864f858d34330 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Fri, 3 Dec 2010 15:57:58 -0800 Subject: [PATCH 13/20] Documentation improvements. --- README.md | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index a52aeb89eff..17a60203f90 100644 --- a/README.md +++ b/README.md @@ -18,10 +18,10 @@ There are several options to easily customize the visualization: } // in this case the last item is directly added again to the top of the ticker }); -There are also several events fired: -beforeScroll // directly before the ticker scrolls -afterScroll // directly after the ticker scrolled -afterFade // directly after the new item was faded in +There are also several events fired:
      +beforeScroll // directly before the ticker scrolls
      +afterScroll // directly after the ticker scrolled
      +afterFade // directly after the new item was faded in
      To bind to an event (the common jQuery UI way): @@ -30,9 +30,9 @@ To bind to an event (the common jQuery UI way): beforeScroll: function(event, ui) { // just do what you like to do } }); -We also provide some methods: -stop // stop the ticker immediately (respectively after a current on going scrolling/fading was finished) -start // start the ticker again +We also provide some methods:
      +stop // stop the ticker immediately (respectively after a current on going scrolling/fading was finished)
      +start // start the ticker again
      To call those methods (the common jQuery UI way): From fd950f35f08799b2ad601eb36a738d5c8a65994a Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 22 Feb 2011 01:43:07 +0100 Subject: [PATCH 14/20] Make ticker more usable in an asynchronous environment (like Ajax). --- tests/unit/ticker/ticker_core.js | 55 ++++++++++++++++--- tests/unit/ticker/ticker_defaults.js | 2 +- tests/unit/ticker/ticker_events.js | 16 +++--- tests/unit/ticker/ticker_methods.js | 12 ++--- tests/unit/ticker/ticker_options.js | 33 +++++------- tests/visual/ticker/ticker.html | 2 +- ui/jquery.ui.ticker.js | 81 ++++++++++++++++------------ 7 files changed, 124 insertions(+), 77 deletions(-) diff --git a/tests/unit/ticker/ticker_core.js b/tests/unit/ticker/ticker_core.js index 4d501a79472..44ca9c8d146 100644 --- a/tests/unit/ticker/ticker_core.js +++ b/tests/unit/ticker/ticker_core.js @@ -8,7 +8,7 @@ var el; module("ticker: core"); -test("nextItem returns null", function() { +test("next called", function() { expect(2); stop(); @@ -16,9 +16,8 @@ test("nextItem returns null", function() { initialTimeout: 0, scrollTime: 0, fadeTime: 0, - nextItem: function(lastItem) { - ok(true, "nextItem is called") - return null; + next: function(lastItem) { + ok(true, "next called"); } }); @@ -40,15 +39,57 @@ test("last item clone retains data and bindings", function() { initialTimeout: 0, scrollTime: 0, fadeTime: 0, - nextItem: function(lastItem) { - ok(true, "nextItem is called"); + next: function(lastItem) { + ok(true, "next called"); equals(lastItem.data("test"), "123", "last item clone retains data"); ok(lastItem.data("events") != null, "last item clone retains events"); - return null; } }); window.setTimeout(function() { start(); }, 200); }); +test("next not called when not ready for next", function() { + expect(1); + stop(); + + $("#ticker").ticker({ + initialTimeout: 0, + scrollTime: 0, + fadeTime: 0, + next: function(lastItem, nextItem) { + ok(true, "next called"); + } + }); + + window.setTimeout(function() { + start(); + }, 1000); +}); + +test("next called when ready for next", function() { + expect(1); + stop(); + + var counter = 0; + + $("#ticker").ticker({ + initialTimeout: 0, + scrollTime: 0, + fadeTime: 0, + next: function(lastItem, nextItem) { + ok(true, "next is called") + if (counter == 1) { + stop(); + } + counter++; + nextItem(lastItem); + } + }); + + window.setTimeout(function() { + start(); + }, 1000); +}); + })(jQuery); diff --git a/tests/unit/ticker/ticker_defaults.js b/tests/unit/ticker/ticker_defaults.js index 2bb157fb00d..c9f3a33c6ad 100644 --- a/tests/unit/ticker/ticker_defaults.js +++ b/tests/unit/ticker/ticker_defaults.js @@ -10,7 +10,7 @@ var ticker_defaults = { mouseOffTimeout: 4000, scrollTime: 800, fadeTime: 1000, - nextItem: null + next: function(lastItem, nextItem) { nextItem(lastItem); } }; commonWidgetTests('ticker', { defaults: ticker_defaults }); diff --git a/tests/unit/ticker/ticker_events.js b/tests/unit/ticker/ticker_events.js index 2ef682e0f43..37b9fe7817f 100644 --- a/tests/unit/ticker/ticker_events.js +++ b/tests/unit/ticker/ticker_events.js @@ -13,7 +13,7 @@ test("beforeScroll", function() { initialTimeout: 0, scrollTime: 0, fadeTime: 0, - nextItem: function(lastItem) { return $('
    • TestItem
    • '); }, + next: function(lastItem, nextItem) { nextItem($('
    • TestItem
    • ')); }, beforeScroll: function(event, ui) { ok(true, 'before scrolling fires beforeScroll callback'); equals($("#ticker li").length, 6, "list does have all items"); @@ -33,7 +33,7 @@ test("afterScroll", function() { initialTimeout: 0, scrollTime: 0, fadeTime: 10000, - nextItem: function(lastItem) { return $('
    • TestItem
    • '); }, + next: function(lastItem, nextItem) { nextItem($('
    • TestItem
    • ')); }, afterScroll: function(event, ui) { ok(true, 'after scrolling fires afterScroll callback'); equals($("#ticker li").length, 6, "list does have all items"); @@ -54,7 +54,7 @@ test("afterFade", function() { initialTimeout: 0, scrollTime: 0, fadeTime: 100, - nextItem: function(lastItem) { return $('
    • TestItem
    • '); }, + next: function(lastItem, nextItem) { nextItem($('
    • TestItem
    • ')); }, afterFade: function(event, ui) { ok(true, 'after fade fires afterFade callback'); equals($("#ticker li").length, 6, "list does have all items"); @@ -67,7 +67,7 @@ test("afterFade", function() { window.setTimeout(function() { start(); }, 300); }); -test("correct order of nextItem call and events", function() { +test("correct order of next called and events", function() { expect(4); stop(); @@ -77,11 +77,11 @@ test("correct order of nextItem call and events", function() { initialTimeout: 0, scrollTime: 50, fadeTime: 50, - nextItem: function(lastItem) { + next: function(lastItem, nextItem) { if (counter == 0) { - ok(true, "nextItem was called first") + ok(true, "next was called first") } - return $('
    • TestItem
    • '); + nextItem($('
    • TestItem
    • ')); }, beforeScroll: function(event, ui) { if (counter == 0) { @@ -100,7 +100,7 @@ test("correct order of nextItem call and events", function() { } }); - window.setTimeout(function() { start(); }, 200); + window.setTimeout(function() { start(); }, 400); }); })(jQuery); diff --git a/tests/unit/ticker/ticker_methods.js b/tests/unit/ticker/ticker_methods.js index 21d4edda38c..0ef3e01ec36 100644 --- a/tests/unit/ticker/ticker_methods.js +++ b/tests/unit/ticker/ticker_methods.js @@ -39,9 +39,9 @@ test("initial stop", function() { $("#ticker").ticker({ initialTimeout: 100, - nextItem: function(lastItem) { + next: function(lastItem, nextItem) { ok(false, "ticker should not scroll after it was stopped"); - return lastItem; + nextItem(lastItem); } }); $("#ticker").ticker("stop"); @@ -61,16 +61,16 @@ test("stop after scroll", function() { mouseOffTimeout: 100, scrollTime: 0, fadeTime: 0, - nextItem: function(lastItem) { + next: function(lastItem, nextItem) { if (counter == 0) { ok(true, "ticker scrolled one time"); $("#ticker").ticker("stop"); counter++; - return lastItem; + nextItem(lastItem); } else { ok(false, "ticker should not scroll after it was stopped"); - return lastItem; + nextItem(lastItem); } } }); @@ -87,7 +87,7 @@ test("start", function() { $("#ticker").ticker({ active: false, initialTimeout: 0, - nextItem: function(lastItem) { + next: function(lastItem, nextItem) { if (started) { ok(true, "ticker scrolled after it was started"); $("#ticker").ticker("stop"); diff --git a/tests/unit/ticker/ticker_options.js b/tests/unit/ticker/ticker_options.js index 8be103670a9..5c5a2ec3d35 100644 --- a/tests/unit/ticker/ticker_options.js +++ b/tests/unit/ticker/ticker_options.js @@ -11,9 +11,9 @@ test("{initalTimout: 200}", function() { var nextCalled = false; $("#ticker").ticker({ initialTimeout: 200, - nextItem: function(lastItem) { + next: function(lastItem, nextItem) { nextCalled = true; - return lastItem; + nextItem(lastItem); } }); @@ -37,9 +37,9 @@ test("{initialTimeout: 200} after calling start method", function() { var nextCalled = false; $("#ticker").ticker({ initialTimeout: 200, - nextItem: function(lastItem) { + next: function(lastItem, nextItem) { nextCalled = true; - return lastItem; + nextItem(lastItem); } }); @@ -66,22 +66,21 @@ test("{mouseOffTimeout: 100}", function() { var counter = 0; - var nextCalled = false; $("#ticker").ticker({ initialTimeout: 0, mouseOnTimeout: 10000, mouseOffTimeout: 100, - nextItem: function(lastItem) { + next: function(lastItem, nextItem) { ok(true, "Next called (one time after init and one time afterwards"); if (counter == 1) { $("#ticker").ticker("stop"); } counter++; - return lastItem; + nextItem(lastItem); } }); - window.setTimeout(function() { start(); }, 400 ); + window.setTimeout(function() { start(); }, 1000 ); }); test("{mouseOnTimeout: 100}", function() { @@ -90,39 +89,35 @@ test("{mouseOnTimeout: 100}", function() { var counter = 0; - var nextCalled = false; - $("#ticker").ticker({ initialTimeout: 0, mouseOnTimeout: 100, mouseOffTimeout: 10000, - nextItem: function(lastItem) { + next: function(lastItem, nextItem) { ok(true, "Next called (one time after init and one time afterwards"); if (counter == 1) { $("#ticker").ticker("stop"); } counter++; - return lastItem; + nextItem(lastItem); } }); $("#ticker").simulate("mouseover"); - window.setTimeout(function() { start(); }, 400 ); + window.setTimeout(function() { start(); }, 1000 ); }); -test('{nextItem: function() {return $("TestItem")}}', function() { +test('{next: function() { next($("TestItem")) }}', function() { expect(2); stop(); - - var nextCalled = false; - + $("#ticker").ticker({ initialTimeout: 0, scrollTime: 0, fadeTime: 0, mouseOffTimeout: 10000, - nextItem: function(lastItem) { - return $("
    • TestItem
    • "); + next: function(lastItem, nextItem) { + nextItem($("
    • TestItem
    • ")); } }); diff --git a/tests/visual/ticker/ticker.html b/tests/visual/ticker/ticker.html index f9bfed7a743..dc69960f782 100644 --- a/tests/visual/ticker/ticker.html +++ b/tests/visual/ticker/ticker.html @@ -13,7 +13,7 @@ $(function() { var i = 0; $("#ticker").ticker({ - nextItem: function(lastItem) { return lastItem; } + next: function(lastItem, nextItem) { nextItem(lastItem); } }); }) diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index 9ea24a8bf2d..a6b30c397ce 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -23,7 +23,7 @@ $.widget( "ui.ticker", { mouseOffTimeout: 4000, scrollTime: 800, fadeTime: 1000, - nextItem: null + next: function(lastItem, nextItem) { nextItem(lastItem); } }, _create: function() { @@ -43,7 +43,7 @@ $.widget( "ui.ticker", { self.speed = options.mouseOnTimeout; if (options.active && self.timeoutId !== null) { window.clearTimeout(self.timeoutId); - self.timeoutId = window.setTimeout(function() { self._scroll(); }, self.speed); + self.timeoutId = window.setTimeout(function() {self._scroll();}, self.speed); } }) .bind( "mouseleave.ticker", function() { @@ -53,7 +53,7 @@ $.widget( "ui.ticker", { self.speed = options.mouseOffTimeout; if (options.active && self.timeoutId !== null) { window.clearTimeout(self.timeoutId); - self.timeoutId = window.setTimeout(function() { self._scroll(); }, self.speed); + self.timeoutId = window.setTimeout(function() {self._scroll();}, self.speed); } }); @@ -73,9 +73,11 @@ $.widget( "ui.ticker", { _init: function() { var self = this, options = self.options; + + self.readyForNext = true; if (options.active) { - self.timeoutId = window.setTimeout(function() { self._scroll() }, options.initialTimeout); + self.timeoutId = window.setTimeout(function() {self._scroll()}, options.initialTimeout); } }, @@ -134,42 +136,51 @@ $.widget( "ui.ticker", { _scroll: function() { var self = this, - options = self.options, - newItem, - lastItem; + options = self.options; - lastItem = self.element.children().last().clone(true); - lastItem.removeClass(itemClasses + " ui-state-hover ui-state-focus"); - - if (self.options.next !== null) { - newItem = self.options.nextItem(lastItem); - - if (newItem != null && newItem.length > 0) { - self._trigger('beforeScroll'); - - newItem.addClass(itemClasses); - self._addItemBindings(newItem); - newItem - .hide() - .prependTo(self.element) - .css('visibility', 'hidden') - .slideDown(options.scrollTime, function() { - $( this ) - .fadeTo(0, 0) - .css('visibility', 'visible') - .fadeTo(options.fadeTime, 1, function() { - self._trigger('afterFade'); - }); - self.element.children().last().remove(); - self._trigger('afterScroll'); - }); - } + if (self.options.next !== null && self.readyForNext) { + var lastItem = self.element.children().last().clone(true); + lastItem.removeClass(itemClasses + " ui-state-hover ui-state-focus"); + self.readyForNext = false; + self.options.next(lastItem, function() { + self._nextItem.apply(self, arguments); + }); } if (options.active) { - self.timeoutId = window.setTimeout(function() { self._scroll(); }, self.speed); + self.timeoutId = window.setTimeout(function() {self._scroll();}, self.speed); } }, + + _nextItem: function(nextItem) { + var self = this, + options = self.options; + + if (nextItem != null && nextItem.length > 0) { + self._trigger('beforeScroll'); + + nextItem.addClass(itemClasses); + self._addItemBindings(nextItem); + nextItem + .hide() + .prependTo(self.element) + .css('visibility', 'hidden') + .slideDown(options.scrollTime, function() { + $( this ) + .fadeTo(0, 0) + .css('visibility', 'visible') + .fadeTo(options.fadeTime, 1, function() { + self._trigger('afterFade'); + }); + self.element.children().last().remove(); + self.readyForNext = true; + self._trigger('afterScroll'); + }); + } + else { + self.readyForNext = true; + } + }, _setOption: function( key, value ) { $.Widget.prototype._setOption.apply( this, arguments ); @@ -203,7 +214,7 @@ $.widget( "ui.ticker", { options.active = true; if (self.timeoutId === null) { - self.timeoutId = window.setTimeout(function() { self._scroll(); }, options.initialTimeout); + self.timeoutId = window.setTimeout(function() {self._scroll();}, options.initialTimeout); } } }); From 6a3a9ee324702c821fc4314762cf635ad2c63654 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 22 Feb 2011 01:51:30 +0100 Subject: [PATCH 15/20] Updated docs. --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 17a60203f90..536223b9428 100644 --- a/README.md +++ b/README.md @@ -13,11 +13,13 @@ There are several options to easily customize the visualization: mouseOffTimeout: 4000, // the timeout before the next item shows up when the mouse pointer is somewhere else scrollTime: 1200, // the times it takes to scroll down the item list fadeTime: 1000, // the time it takes to fade in the next item at the top of the item list - nextItem: function(lastItem) { // this function provides a clone of the last item on the list that will be removed next - return $(lastItem); // the item that should be added next to the ticker (should be a jQuery
    • item) - } // in this case the last item is directly added again to the top of the ticker + next: function(lastItem, nextItem) { // this function provides a clone of the last item on the list that will be removed next + nextItem($(lastItem)); // the item that should be added next to the ticker must be provided to nextItem function (should be a jQuery
    • item) + } // in this example case (the default) the last item is directly added again to the top of the ticker }); +If the nextItem function was not called before the next scroll would take place then the next scroll is passed. + There are also several events fired:
      beforeScroll // directly before the ticker scrolls
      afterScroll // directly after the ticker scrolled
      From 57617836020012b4e7388919728d024d3d8428f7 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Tue, 22 Feb 2011 20:16:46 +0100 Subject: [PATCH 16/20] Exchanged children for find selector as children selector does not work when the main ticker is an id instead of a HTML class. Also removed some whitespaces. --- ui/jquery.ui.ticker.js | 64 +++++++++++++++++++++--------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index a6b30c397ce..6b29297ceab 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -11,11 +11,11 @@ * jquery.ui.core.js * jquery.ui.widget.js */ -(function( $, undefined ) { +(function($, undefined) { var itemClasses = "ui-ticker-content ui-widget-content ui-helper-reset ui-state-default ui-corner-all"; -$.widget( "ui.ticker", { +$.widget("ui.ticker", { options: { active: true, initialTimeout: 4000, @@ -35,9 +35,9 @@ $.widget( "ui.ticker", { self.speed = options.mouseOffTimeout; self.element - .addClass( "ui-ticker ui-widget ui-corner-all" ) - .bind( "mouseenter.ticker", function() { - if ( options.disabled ) { + .addClass("ui-ticker ui-widget ui-corner-all") + .bind("mouseenter.ticker", function() { + if (options.disabled) { return; } self.speed = options.mouseOnTimeout; @@ -46,8 +46,8 @@ $.widget( "ui.ticker", { self.timeoutId = window.setTimeout(function() {self._scroll();}, self.speed); } }) - .bind( "mouseleave.ticker", function() { - if ( options.disabled ) { + .bind("mouseleave.ticker", function() { + if (options.disabled) { return; } self.speed = options.mouseOffTimeout; @@ -57,8 +57,8 @@ $.widget( "ui.ticker", { } }); - self.element.children( "li" ).addClass(itemClasses); - self._addItemBindings(self.element.children( "li" )); + self.element.find("li").addClass(itemClasses); + self._addItemBindings(self.element.find("li")); var style = self.element.attr("style"); if (style === undefined || style === null) { @@ -90,9 +90,9 @@ $.widget( "ui.ticker", { } self.element.unbind(".ticker"); - self.element.children( "li" ).unbind(".ticker"); - self.element.removeClass( "ui-ticker ui-widget ui-corner-all" ); - self.element.children( "li" ).removeClass(itemClasses + " ui-state-hover ui-state-focus"); + self.element.find("li").unbind(".ticker"); + self.element.removeClass("ui-ticker ui-widget ui-corner-all"); + self.element.find("li").removeClass(itemClasses + " ui-state-hover ui-state-focus"); if (self.originalStyle === null) { self.element.removeAttr("style"); @@ -101,36 +101,36 @@ $.widget( "ui.ticker", { self.element.attr("style", self.originalStyle); } - return $.Widget.prototype.destroy.call( self ); + return $.Widget.prototype.destroy.call(self); }, _addItemBindings: function(item) { var options = this.options; item - .bind( "mouseenter.ticker", function() { - if ( options.disabled ) { + .bind("mouseenter.ticker", function() { + if (options.disabled) { return; } - $( this ).addClass( "ui-state-hover" ); + $(this).addClass("ui-state-hover"); }) - .bind( "mouseleave.ticker", function() { - if ( options.disabled ) { + .bind("mouseleave.ticker", function() { + if (options.disabled) { return; } - $( this ).removeClass( "ui-state-hover" ); + $(this).removeClass("ui-state-hover"); }) - .bind( "focus.ticker", function() { - if ( options.disabled ) { + .bind("focus.ticker", function() { + if (options.disabled) { return; } - $( this ).addClass( "ui-state-focus" ); + $(this).addClass("ui-state-focus"); }) - .bind( "blur.ticker", function() { - if ( options.disabled ) { + .bind("blur.ticker", function() { + if (options.disabled) { return; } - $( this ).removeClass( "ui-state-focus" ); + $(this).removeClass("ui-state-focus"); }); }, @@ -139,7 +139,7 @@ $.widget( "ui.ticker", { options = self.options; if (self.options.next !== null && self.readyForNext) { - var lastItem = self.element.children().last().clone(true); + var lastItem = self.element.find("li").last().clone(true); lastItem.removeClass(itemClasses + " ui-state-hover ui-state-focus"); self.readyForNext = false; self.options.next(lastItem, function() { @@ -166,13 +166,13 @@ $.widget( "ui.ticker", { .prependTo(self.element) .css('visibility', 'hidden') .slideDown(options.scrollTime, function() { - $( this ) + $(this) .fadeTo(0, 0) .css('visibility', 'visible') .fadeTo(options.fadeTime, 1, function() { self._trigger('afterFade'); }); - self.element.children().last().remove(); + self.element.find("li").last().remove(); self.readyForNext = true; self._trigger('afterScroll'); }); @@ -182,8 +182,8 @@ $.widget( "ui.ticker", { } }, - _setOption: function( key, value ) { - $.Widget.prototype._setOption.apply( this, arguments ); + _setOption: function(key, value) { + $.Widget.prototype._setOption.apply(this, arguments); switch (key) { case "active": @@ -219,8 +219,8 @@ $.widget( "ui.ticker", { } }); -$.extend( $.ui.ticker, { +$.extend($.ui.ticker, { version: "@VERSION" }); -})( jQuery ); +})(jQuery); From 3e1d69b4ef1f7d934522565270d195257704234d Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Fri, 25 Feb 2011 15:22:33 -0800 Subject: [PATCH 17/20] Updated the docs. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 536223b9428..604f5a55eb1 100644 --- a/README.md +++ b/README.md @@ -28,12 +28,12 @@ afterFade // directly after the new item was faded in
      To bind to an event (the common jQuery UI way): $("#ticker").ticker({ - nextItem: function(lastItem) { return $('
    • TestItem
    • '); }, + nextItem: function(lastItem) { nextItem($('
    • TestItem
    • ')); }, beforeScroll: function(event, ui) { // just do what you like to do } }); We also provide some methods:
      -stop // stop the ticker immediately (respectively after a current on going scrolling/fading was finished)
      +stop // stop the ticker immediately (respectively after the scrolling/fading is finished)
      start // start the ticker again
      To call those methods (the common jQuery UI way): From 9fd975376b409aa1e5665784858618ba804b2e97 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Fri, 25 Feb 2011 15:25:25 -0800 Subject: [PATCH 18/20] Another documentation udpate. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 604f5a55eb1..3bef3dffc33 100644 --- a/README.md +++ b/README.md @@ -14,7 +14,7 @@ There are several options to easily customize the visualization: scrollTime: 1200, // the times it takes to scroll down the item list fadeTime: 1000, // the time it takes to fade in the next item at the top of the item list next: function(lastItem, nextItem) { // this function provides a clone of the last item on the list that will be removed next - nextItem($(lastItem)); // the item that should be added next to the ticker must be provided to nextItem function (should be a jQuery
    • item) + nextItem($(lastItem)); // the item (a jQuery
    • object) that should be added next to the ticker must be provided as parameter to nextItem } // in this example case (the default) the last item is directly added again to the top of the ticker }); @@ -28,7 +28,7 @@ afterFade // directly after the new item was faded in
      To bind to an event (the common jQuery UI way): $("#ticker").ticker({ - nextItem: function(lastItem) { nextItem($('
    • TestItem
    • ')); }, + nextItem: function(lastItem, nextItem) { nextItem($('
    • TestItem
    • ')); }, beforeScroll: function(event, ui) { // just do what you like to do } }); From e4c334d0210fc35b66ff01f9b88162c22cc39d2d Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Mon, 28 Feb 2011 08:25:45 -0800 Subject: [PATCH 19/20] Doc update. --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3bef3dffc33..d7ec1ad91ae 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ [jQuery UI](http://jqueryui.com/) - Interactions and Widgets for the web ================================ -This fork of jQuery UI includes our brand new Ticker. We also have a [live demo](http://medihack.github.com/tickerdemo/) with some customized style sheets (for having a similar look like Twitter). +This fork of jQuery UI includes a Twitter like ticker in the ticker branch. A [live demo](http://medihack.github.com/tickerdemo/) with some customized style sheets can be found [here](http://medihack.github.com/tickerdemo/). -The Ticker in its raw form is fully compatible with the jQuery UI Theming framework. It is also quite flexible and well tested. +The Ticker in its raw form is fully compatible with the jQuery UI Theming framework. It is also quite flexible and fully Unit tested (qunit). There are several options to easily customize the visualization: From e7b2c7cfd786f16833cec31091acd0fd4d150ea5 Mon Sep 17 00:00:00 2001 From: Kai Schlamp Date: Mon, 7 Mar 2011 02:30:17 +0100 Subject: [PATCH 20/20] Also allow the next item to be returned in the next function. Always make sure next item is becoming a jQuery object. --- README.md | 6 +++-- tests/unit/ticker/ticker_core.js | 38 ++++++++++++++++++++++++++++++++ ui/jquery.ui.ticker.js | 13 +++++++---- 3 files changed, 51 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 536223b9428..1de2c0e07db 100644 --- a/README.md +++ b/README.md @@ -14,8 +14,10 @@ There are several options to easily customize the visualization: scrollTime: 1200, // the times it takes to scroll down the item list fadeTime: 1000, // the time it takes to fade in the next item at the top of the item list next: function(lastItem, nextItem) { // this function provides a clone of the last item on the list that will be removed next - nextItem($(lastItem)); // the item that should be added next to the ticker must be provided to nextItem function (should be a jQuery
    • item) - } // in this example case (the default) the last item is directly added again to the top of the ticker + return $("
    • next item
    • "); // the next item for the ticker can be returned + // or + nextItem($("
    • next item
    • ")); // or be provided to the nextItem function (useful for asynchronous Ajax requests) + } // the next item must be wrapped in a
    • tag }); If the nextItem function was not called before the next scroll would take place then the next scroll is passed. diff --git a/tests/unit/ticker/ticker_core.js b/tests/unit/ticker/ticker_core.js index 44ca9c8d146..805dd8be8e0 100644 --- a/tests/unit/ticker/ticker_core.js +++ b/tests/unit/ticker/ticker_core.js @@ -49,6 +49,44 @@ test("last item clone retains data and bindings", function() { window.setTimeout(function() { start(); }, 200); }); +test("next item can be provided by returning it in method next", function() { + expect(1); + stop(); + + $("#ticker").ticker({ + initialTimeout: 0, + scrollTime: 0, + fadeTime: 0, + next: function(lastItem) { + return $("
    • Next Item
    • "); + } + }); + + window.setTimeout(function() { + equals($("#ticker li:first").text(), "Next Item", "ticker has not scrolled"); + start(); + }, 100); +}); + +test("next item can be provided by calling nextItem method", function() { + expect(1); + stop(); + + $("#ticker").ticker({ + initialTimeout: 0, + scrollTime: 0, + fadeTime: 0, + next: function(lastItem, nextItem) { + nextItem($("
    • Next Item
    • ")); + } + }); + + window.setTimeout(function() { + equals($("#ticker li:first").text(), "Next Item", "ticker has not scrolled"); + start(); + }, 100); +}); + test("next not called when not ready for next", function() { expect(1); stop(); diff --git a/ui/jquery.ui.ticker.js b/ui/jquery.ui.ticker.js index 6b29297ceab..0343aa6003b 100644 --- a/ui/jquery.ui.ticker.js +++ b/ui/jquery.ui.ticker.js @@ -142,9 +142,12 @@ $.widget("ui.ticker", { var lastItem = self.element.find("li").last().clone(true); lastItem.removeClass(itemClasses + " ui-state-hover ui-state-focus"); self.readyForNext = false; - self.options.next(lastItem, function() { + var nextItem = self.options.next(lastItem, function() { self._nextItem.apply(self, arguments); }); + if (nextItem) { + self._nextItem(nextItem); + } } if (options.active) { @@ -159,9 +162,11 @@ $.widget("ui.ticker", { if (nextItem != null && nextItem.length > 0) { self._trigger('beforeScroll'); - nextItem.addClass(itemClasses); - self._addItemBindings(nextItem); - nextItem + var $nextItem = $(nextItem); + + $nextItem.addClass(itemClasses); + self._addItemBindings($nextItem); + $nextItem .hide() .prependTo(self.element) .css('visibility', 'hidden')