Refactor queueing system to allow auto-dequeuing to use dequeue directly and
authorYehuda Katz <wycats@gmail.com>
Thu, 16 Jul 2009 07:32:39 +0000 (07:32 +0000)
committerYehuda Katz <wycats@gmail.com>
Thu, 16 Jul 2009 07:32:39 +0000 (07:32 +0000)
therefore require dequeue to always leave the element it has dequeued on
the queue.

  - In the fx queue, a progress sentinel is added when a queue element
    is dequeued.
  - The sentinel is ignored when dequeue is called explicitly
  - When adding a new element to the fx queue, queue() checks if
    the progress sentinel is present. If not, it calls dequeue()

src/data.js
test/unit/data.js

index 9cc76c6..03116e4 100644 (file)
@@ -63,30 +63,37 @@ jQuery.extend({
                }\r
        },\r
        queue: function( elem, type, data ) {\r
-               if ( elem ){\r
+               if( !elem ) return;\r
 \r
-                       type = (type || "fx") + "queue";\r
+               type = (type || "fx") + "queue";\r
+               var q = jQuery.data( elem, type );\r
 \r
-                       var q = jQuery.data( elem, type );\r
+               // Speed up dequeue by getting out quickly if this is just a lookup\r
+               if( !data ) return q || [];\r
 \r
-                       if ( !q || jQuery.isArray(data) )\r
-                               q = jQuery.data( elem, type, jQuery.makeArray(data) );\r
-                       else if( data )\r
-                               q.push( data );\r
+               if ( !q || jQuery.isArray(data) )\r
+                       q = jQuery.data( elem, type, jQuery.makeArray(data) );\r
+               else\r
+                       q.push( data );\r
 \r
-               }\r
                return q;\r
        },\r
 \r
        dequeue: function( elem, type ){\r
-               var queue = jQuery.queue( elem, type ),\r
-                       fn = queue.shift();\r
+               type = type || "fx";\r
+\r
+               var queue = jQuery.queue( elem, type ), fn = queue.shift();\r
 \r
-               if( !type || type === "fx" )\r
-                       fn = queue[0];\r
+               // If the fx queue is dequeued, always remove the progress sentinel\r
+               if( fn === "inprogress" ) fn = queue.shift();\r
 \r
-               if( fn !== undefined )\r
-                       fn.call(elem, function() { jQuery(elem).dequeue(type); });\r
+               if( fn ) {\r
+                       // Add a progress sentinel to prevent the fx queue from being\r
+                       // automatically dequeued\r
+                       if( type == "fx" ) queue.unshift("inprogress");\r
+\r
+                       fn.call(elem, function() { jQuery.dequeue(elem, type); });\r
+               }\r
        }\r
 });\r
 \r
@@ -129,8 +136,8 @@ jQuery.fn.extend({
                return this.each(function(i, elem){\r
                        var queue = jQuery.queue( this, type, data );\r
 \r
-                       if( type == "fx" && queue.length == 1 )\r
-                               queue[0].call(this, function() { jQuery(elem).dequeue(type); });\r
+                       if( type == "fx" && queue[0] !== "inprogress" )\r
+                               jQuery.dequeue( this, type )\r
                });\r
        },\r
        dequeue: function(type){\r
index 14483a1..6b79da2 100644 (file)
@@ -113,20 +113,23 @@ test(".removeData()", function() {
 });\r
 \r
 test("queue() defaults to 'fx' type", function () {\r
-       expect(2);\r
+       expect(1);\r
        stop();\r
 \r
+       var counter = 0;\r
+\r
        var $foo = jQuery("#foo");\r
-       $foo.queue("fx", [ "sample", "array" ]);\r
-       var arr = $foo.queue();\r
-       isSet(arr, [ "sample", "array" ], "queue() got an array set with type 'fx'");\r
-       $foo.queue([ "another", "one" ]);\r
-       var arr = $foo.queue("fx");\r
-       isSet(arr, [ "another", "one" ], "queue('fx') got an array set with no type");\r
-       // clean up after test\r
-       $foo.queue([]);\r
 \r
-       start();\r
+       $foo.queue(function() {\r
+               var self = this;\r
+               setTimeout(function() {\r
+                       jQuery(self).dequeue("fx");\r
+                       start();\r
+               }, 200);\r
+       }).queue(function() {\r
+               ok( "dequeuing 'fx' calls queues created with no name" )\r
+       });\r
+\r
 });\r
 \r
 test("queue() with other types",function() {\r
@@ -162,9 +165,6 @@ test("queue() with other types",function() {
        \r
        equals( counter, 4, "Testing previous call to dequeue" );\r
        equals( $div.queue('foo').length, 0, "Testing queue length" );\r
-       \r
-       // Clean up\r
-       $div.removeData();\r
 });\r
 \r
 test("queue(name) passes in the next item in the queue as a parameter", function() {\r
@@ -184,8 +184,6 @@ test("queue(name) passes in the next item in the queue as a parameter", function
        });\r
        \r
        div.dequeue("foo");\r
-       \r
-       div.removeData();\r
 });\r
 \r
 test("queue(name) passes in the next item in the queue as a parameter", function() {\r
@@ -205,27 +203,27 @@ test("queue(name) passes in the next item in the queue as a parameter", function
        });\r
        \r
        div.dequeue("foo");\r
-       \r
-       div.removeData();\r
 });\r
 \r
 test("queue() passes in the next item in the queue as a parameter to fx queues", function() {\r
        expect(2);\r
+       stop();\r
        \r
        var div = jQuery({});\r
        var counter = 0;\r
        \r
        div.queue(function(next) {\r
                equals(++counter, 1, "Dequeueing");\r
-               next();\r
+               var self = this;\r
+               setTimeout(function() { next() }, 500);\r
        }).queue(function(next) {\r
                equals(++counter, 2, "Next was called");\r
                next();\r
+               start();\r
        }).queue("bar", function() {\r
                equals(++counter, 3, "Other queues are not triggered by next()")\r
        });\r
-       \r
-       div.removeData();\r
+\r
 });\r
 \r
 test("clearQueue(name) clears the queue", function() {\r
@@ -245,8 +243,6 @@ test("clearQueue(name) clears the queue", function() {
        div.dequeue("foo");\r
        \r
        equals(counter, 1, "the queue was cleared");\r
-       \r
-       div.removeData();\r
 });\r
 \r
 test("clearQueue() clears the fx queue", function() {\r
@@ -257,7 +253,8 @@ test("clearQueue() clears the fx queue", function() {
        \r
        div.queue(function(next) {\r
                counter++;\r
-               setTimeout(function() { jQuery(this).clearQueue(); next(); }, 50);\r
+               var self = this;\r
+               setTimeout(function() { jQuery(self).clearQueue(); next(); }, 50);\r
        }).queue(function(next) {\r
                counter++;\r
        });\r