aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJörn Zaefferer <joern.zaefferer@gmail.com>2011-05-11 19:49:16 +0200
committerJörn Zaefferer <joern.zaefferer@gmail.com>2011-05-11 19:49:16 +0200
commit83424c6c334406d427d9eef8e4fe22fd9da0a37a (patch)
treebcc89c0d30aaf9d2333246075a43c03c5fabeb2a
parent0352c2c71f32553612301f57741f249476234746 (diff)
parentb9153258b0f0edbff49496ed16d2aa93bec07d95 (diff)
downloadjquery-ui-83424c6c334406d427d9eef8e4fe22fd9da0a37a.tar.gz
jquery-ui-83424c6c334406d427d9eef8e4fe22fd9da0a37a.zip
Merge branch 'master' of github.com:jquery/jquery-ui
-rw-r--r--README.md2
-rw-r--r--demos/autocomplete/maxheight.html1
-rw-r--r--tests/unit/widget/widget.html1
-rw-r--r--tests/unit/widget/widget_extend.js104
-rw-r--r--ui/jquery.ui.datepicker.js2
-rw-r--r--ui/jquery.ui.draggable.js4
-rw-r--r--ui/jquery.ui.menu.js13
-rw-r--r--ui/jquery.ui.slider.js50
-rw-r--r--ui/jquery.ui.tabs.js46
-rw-r--r--ui/jquery.ui.widget.js29
10 files changed, 166 insertions, 86 deletions
diff --git a/README.md b/README.md
index 9a0d7c5c5..ace5fe2de 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@ If you want to use jQuery UI, go to [jqueryui.com](http://jqueryui.com) to get s
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).
-For commiters
+For committers
---
When looking at pull requests, first check for [proper commit messages](http://wiki.jqueryui.com/w/page/12137724/Bug-Fixing-Guide).
diff --git a/demos/autocomplete/maxheight.html b/demos/autocomplete/maxheight.html
index fc0b4840c..c4f9769c3 100644
--- a/demos/autocomplete/maxheight.html
+++ b/demos/autocomplete/maxheight.html
@@ -8,6 +8,7 @@
<script src="../../ui/jquery.ui.core.js"></script>
<script src="../../ui/jquery.ui.widget.js"></script>
<script src="../../ui/jquery.ui.position.js"></script>
+ <script src="../../ui/jquery.ui.menu.js"></script>
<script src="../../ui/jquery.ui.autocomplete.js"></script>
<link rel="stylesheet" href="../demos.css">
<style>
diff --git a/tests/unit/widget/widget.html b/tests/unit/widget/widget.html
index e74abb317..183537612 100644
--- a/tests/unit/widget/widget.html
+++ b/tests/unit/widget/widget.html
@@ -14,6 +14,7 @@
<script src="../testsuite.js"></script>
<script src="widget_core.js"></script>
+ <script src="widget_extend.js"></script>
<script src="../swarminject.js"></script>
</head>
diff --git a/tests/unit/widget/widget_extend.js b/tests/unit/widget/widget_extend.js
new file mode 100644
index 000000000..fb78ecfb7
--- /dev/null
+++ b/tests/unit/widget/widget_extend.js
@@ -0,0 +1,104 @@
+test( "$.widget.extend()", function() {
+ expect( 26 );
+
+ var settings = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" },
+ options = { xnumber2: 1, xstring2: "x", xxx: "newstring" },
+ optionsCopy = { xnumber2: 1, xstring2: "x", xxx: "newstring" },
+ merged = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "x", xxx: "newstring" },
+ deep1 = { foo: { bar: true } },
+ deep1copy = { foo: { bar: true } },
+ deep2 = { foo: { baz: true }, foo2: document },
+ deep2copy = { foo: { baz: true }, foo2: document },
+ deepmerged = { foo: { bar: true, baz: true }, foo2: document },
+ arr = [1, 2, 3],
+ nestedarray = { arr: arr },
+ ret;
+
+ $.widget.extend( settings, options );
+ deepEqual( settings, merged, "Check if extended: settings must be extended" );
+ deepEqual( options, optionsCopy, "Check if not modified: options must not be modified" );
+
+ $.widget.extend( deep1, deep2 );
+ deepEqual( deep1.foo, deepmerged.foo, "Check if foo: settings must be extended" );
+ deepEqual( deep2.foo, deep2copy.foo, "Check if not deep2: options must not be modified" );
+ equal( deep1.foo2, document, "Make sure that a deep clone was not attempted on the document" );
+
+ strictEqual( $.widget.extend({}, nestedarray).arr, arr, "Don't clone arrays" );
+ ok( $.isPlainObject( $.widget.extend({ arr: arr }, { arr: {} }).arr ), "Cloned object heve to be an plain object" );
+
+ var empty = {};
+ var optionsWithLength = { foo: { length: -1 } };
+ $.widget.extend( empty, optionsWithLength );
+ deepEqual( empty.foo, optionsWithLength.foo, "The length property must copy correctly" );
+
+ empty = {};
+ var optionsWithDate = { foo: { date: new Date } };
+ $.widget.extend( empty, optionsWithDate );
+ deepEqual( empty.foo, optionsWithDate.foo, "Dates copy correctly" );
+
+ var myKlass = function() {};
+ var customObject = new myKlass();
+ var optionsWithCustomObject = { foo: { date: customObject } };
+ empty = {};
+ $.widget.extend( empty, optionsWithCustomObject );
+ strictEqual( empty.foo.date, customObject, "Custom objects copy correctly (no methods)" );
+
+ // Makes the class a little more realistic
+ myKlass.prototype = { someMethod: function(){} };
+ empty = {};
+ $.widget.extend( empty, optionsWithCustomObject );
+ strictEqual( empty.foo.date, customObject, "Custom objects copy correctly" );
+
+ ret = $.widget.extend({ foo: 4 }, { foo: new Number(5) } );
+ equal( ret.foo, 5, "Wrapped numbers copy correctly" );
+
+ var nullUndef;
+ nullUndef = $.widget.extend( {}, options, { xnumber2: null } );
+ strictEqual( nullUndef.xnumber2, null, "Check to make sure null values are copied");
+
+ nullUndef = $.widget.extend( {}, options, { xnumber2: undefined } );
+ strictEqual( nullUndef.xnumber2, options.xnumber2, "Check to make sure undefined values are not copied");
+
+ nullUndef = $.widget.extend( {}, options, { xnumber0: null } );
+ strictEqual( nullUndef.xnumber0, null, "Check to make sure null values are inserted");
+
+ var target = {};
+ var recursive = { foo:target, bar:5 };
+ $.widget.extend( target, recursive );
+ deepEqual( target, { foo: {}, bar: 5 }, "Check to make sure a recursive obj doesn't go never-ending loop by not copying it over" );
+
+ ret = $.widget.extend( { foo: [] }, { foo: [0] } ); // 1907
+ equal( ret.foo.length, 1, "Check to make sure a value with coersion 'false' copies over when necessary to fix #1907" );
+
+ ret = $.widget.extend( { foo: "1,2,3" }, { foo: [1, 2, 3] } );
+ strictEqual( typeof ret.foo, "object", "Check to make sure values equal with coersion (but not actually equal) overwrite correctly" );
+
+ ret = $.widget.extend( { foo:"bar" }, { foo:null } );
+ strictEqual( typeof ret.foo, "object", "Make sure a null value doesn't crash with deep extend, for #1908" );
+
+ var obj = { foo:null };
+ $.widget.extend( obj, { foo:"notnull" } );
+ equal( obj.foo, "notnull", "Make sure a null value can be overwritten" );
+
+ var defaults = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" },
+ defaultsCopy = { xnumber1: 5, xnumber2: 7, xstring1: "peter", xstring2: "pan" },
+ options1 = { xnumber2: 1, xstring2: "x" },
+ options1Copy = { xnumber2: 1, xstring2: "x" },
+ options2 = { xstring2: "xx", xxx: "newstringx" },
+ options2Copy = { xstring2: "xx", xxx: "newstringx" },
+ merged2 = { xnumber1: 5, xnumber2: 1, xstring1: "peter", xstring2: "xx", xxx: "newstringx" };
+
+ var settings = $.widget.extend( {}, defaults, options1, options2 );
+ deepEqual( settings, merged2, "Check if extended: settings must be extended" );
+ deepEqual( defaults, defaultsCopy, "Check if not modified: options1 must not be modified" );
+ deepEqual( options1, options1Copy, "Check if not modified: options1 must not be modified" );
+ deepEqual( options2, options2Copy, "Check if not modified: options2 must not be modified" );
+
+ var input = {
+ key: [ 1, 2, 3 ]
+ }
+ var output = $.widget.extend( {}, input );
+ deepEqual( input, output, "don't clone arrays" );
+ input.key[0] = 10;
+ deepEqual( input, output, "don't clone arrays" );
+});
diff --git a/ui/jquery.ui.datepicker.js b/ui/jquery.ui.datepicker.js
index 12323672a..662b49f86 100644
--- a/ui/jquery.ui.datepicker.js
+++ b/ui/jquery.ui.datepicker.js
@@ -1489,7 +1489,7 @@ $.extend(Datepicker.prototype, {
if (drawYear == inst.selectedYear && drawMonth == inst.selectedMonth)
inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
var leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
- var numRows = (isMultiMonth ? 6 : Math.ceil((leadDays + daysInMonth) / 7)); // calculate the number of rows to generate
+ var numRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
var printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
for (var dRow = 0; dRow < numRows; dRow++) { // create date picker rows
calender += '<tr>';
diff --git a/ui/jquery.ui.draggable.js b/ui/jquery.ui.draggable.js
index 774ea4380..d7bc09578 100644
--- a/ui/jquery.ui.draggable.js
+++ b/ui/jquery.ui.draggable.js
@@ -261,7 +261,7 @@ $.widget("ui.draggable", $.ui.mouse, {
_createHelper: function(event) {
var o = this.options;
- var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone() : this.element);
+ var helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper == 'clone' ? this.element.clone().removeAttr('id') : this.element);
if(!helper.parents('body').length)
helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
@@ -580,7 +580,7 @@ $.ui.plugin.add("draggable", "connectToSortable", {
//Now we fake the start of dragging for the sortable instance,
//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
- this.instance.currentItem = $(self).clone().appendTo(this.instance.element).data("sortable-item", true);
+ this.instance.currentItem = $(self).clone().removeAttr('id').appendTo(this.instance.element).data("sortable-item", true);
this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
this.instance.options.helper = function() { return ui.helper[0]; };
diff --git a/ui/jquery.ui.menu.js b/ui/jquery.ui.menu.js
index 5fcb0ac90..41b2e7a1a 100644
--- a/ui/jquery.ui.menu.js
+++ b/ui/jquery.ui.menu.js
@@ -233,15 +233,15 @@ $.widget("ui.menu", {
if ( this._hasScroll() ) {
var borderTop = parseFloat( $.curCSS( this.element[0], "borderTopWidth", true) ) || 0,
- paddingtop = parseFloat( $.curCSS( this.element[0], "paddingTop", true) ) || 0,
- offset = item.offset().top - this.element.offset().top - borderTop - paddingtop,
- scroll = this.element.attr( "scrollTop" ),
+ paddingTop = parseFloat( $.curCSS( this.element[0], "paddingTop", true) ) || 0,
+ offset = item.offset().top - this.element.offset().top - borderTop - paddingTop,
+ scroll = this.element.scrollTop(),
elementHeight = this.element.height(),
itemHeight = item.height();
if ( offset < 0 ) {
- this.element.attr( "scrollTop", scroll + offset );
+ this.element.scrollTop( scroll + offset );
} else if ( offset + itemHeight > elementHeight ) {
- this.element.attr( "scrollTop", scroll + offset - elementHeight + itemHeight );
+ this.element.scrollTop( scroll + offset - elementHeight + itemHeight );
}
}
@@ -406,7 +406,8 @@ $.widget("ui.menu", {
},
_hasScroll: function() {
- return this.element.height() < this.element.attr( "scrollHeight" );
+ // TODO: just use .prop() when we drop support for jQuery <1.6
+ return this.element.height() < this.element[ $.fn.prop ? "prop" : "attr" ]( "scrollHeight" );
},
select: function( event ) {
diff --git a/ui/jquery.ui.slider.js b/ui/jquery.ui.slider.js
index eb6545f62..f0b01d7c0 100644
--- a/ui/jquery.ui.slider.js
+++ b/ui/jquery.ui.slider.js
@@ -36,7 +36,11 @@ $.widget( "ui.slider", $.ui.mouse, {
_create: function() {
var self = this,
- o = this.options;
+ o = this.options,
+ existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
+ handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
+ handleCount = ( o.values && o.values.length ) || 1,
+ handles = [];
this._keySliding = false;
this._mouseSliding = false;
@@ -50,57 +54,35 @@ $.widget( "ui.slider", $.ui.mouse, {
" ui-slider-" + this.orientation +
" ui-widget" +
" ui-widget-content" +
- " ui-corner-all" );
-
- if ( o.disabled ) {
- this.element.addClass( "ui-slider-disabled ui-disabled" );
- }
+ " ui-corner-all" +
+ ( o.disabled ? " ui-slider-disabled ui-disabled" : "" ) );
this.range = $([]);
if ( o.range ) {
if ( o.range === true ) {
- this.range = $( "<div></div>" );
if ( !o.values ) {
o.values = [ this._valueMin(), this._valueMin() ];
}
if ( o.values.length && o.values.length !== 2 ) {
o.values = [ o.values[0], o.values[0] ];
}
- } else {
- this.range = $( "<div></div>" );
- }
-
- this.range
- .appendTo( this.element )
- .addClass( "ui-slider-range" );
-
- if ( o.range === "min" || o.range === "max" ) {
- this.range.addClass( "ui-slider-range-" + o.range );
}
- // note: this isn't the most fittingly semantic framework class for this element,
- // but worked best visually with a variety of themes
- this.range.addClass( "ui-widget-header" );
- }
-
- if ( $( ".ui-slider-handle", this.element ).length === 0 ) {
- $( "<a href='#'></a>" )
+ this.range = $( "<div></div>" )
.appendTo( this.element )
- .addClass( "ui-slider-handle" );
+ .addClass( "ui-slider-range" +
+ // note: this isn't the most fittingly semantic framework class for this element,
+ // but worked best visually with a variety of themes
+ " ui-widget-header" +
+ ( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
}
- if ( o.values && o.values.length ) {
- while ( $(".ui-slider-handle", this.element).length < o.values.length ) {
- $( "<a href='#'></a>" )
- .appendTo( this.element )
- .addClass( "ui-slider-handle" );
- }
+ for ( var i = existingHandles.length; i < handleCount; i += 1 ) {
+ handles.push( handle );
}
- this.handles = $( ".ui-slider-handle", this.element )
- .addClass( "ui-state-default" +
- " ui-corner-all" );
+ this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( self.element ) );
this.handle = this.handles.eq( 0 );
diff --git a/ui/jquery.ui.tabs.js b/ui/jquery.ui.tabs.js
index cce50d3e7..86960cab6 100644
--- a/ui/jquery.ui.tabs.js
+++ b/ui/jquery.ui.tabs.js
@@ -401,52 +401,26 @@ $.widget( "ui.tabs", {
that.xhr.abort();
}
- // if tab may be closed
- if ( options.collapsible ) {
- if ( collapsing ) {
- options.active = false;
-
- that.element.queue( "tabs", function() {
- that._hideTab( event, eventData );
- }).dequeue( "tabs" );
-
- clicked[ 0 ].blur();
- return;
- } else if ( !toHide.length ) {
- that.element.queue( "tabs", function() {
- that._showTab( event, eventData );
- });
-
- // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
- that.load( that.anchors.index( clicked ), event );
-
- clicked[ 0 ].blur();
- return;
- }
+ if ( !toHide.length && !toShow.length ) {
+ throw "jQuery UI Tabs: Mismatching fragment identifier.";
}
- // show new tab
+ if ( toHide.length ) {
+ that.element.queue( "tabs", function() {
+ that._hideTab( event, eventData );
+ });
+ }
if ( toShow.length ) {
- if ( toHide.length ) {
- that.element.queue( "tabs", function() {
- that._hideTab( event, eventData );
- });
- }
that.element.queue( "tabs", function() {
that._showTab( event, eventData );
});
+ // TODO make passing in node possible, see also http://dev.jqueryui.com/ticket/3171
that.load( that.anchors.index( clicked ), event );
- } else {
- throw "jQuery UI Tabs: Mismatching fragment identifier.";
- }
- // Prevent IE from keeping other link focussed when using the back button
- // and remove dotted border from clicked link. This is controlled via CSS
- // in modern browsers; blur() removes focus from address bar in Firefox
- // which can become a usability
- if ( $.browser.msie ) {
clicked[ 0 ].blur();
+ } else {
+ that.element.dequeue( "tabs" );
}
},
diff --git a/ui/jquery.ui.widget.js b/ui/jquery.ui.widget.js
index a74e6b77b..4167fd4e5 100644
--- a/ui/jquery.ui.widget.js
+++ b/ui/jquery.ui.widget.js
@@ -55,7 +55,7 @@ $.widget = function( name, base, prototype ) {
// we need to make the options hash a property directly on the new instance
// otherwise we'll modify the options hash on the prototype that we're
// inheriting from
- basePrototype.options = $.extend( true, {}, basePrototype.options );
+ basePrototype.options = $.widget.extend( {}, basePrototype.options );
$.each( prototype, function( prop, value ) {
if ( $.isFunction( value ) ) {
prototype[ prop ] = (function() {
@@ -83,7 +83,7 @@ $.widget = function( name, base, prototype ) {
}());
}
});
- $[ namespace ][ name ].prototype = $.extend( true, basePrototype, {
+ $[ namespace ][ name ].prototype = $.widget.extend( basePrototype, {
namespace: namespace,
widgetName: name,
widgetEventPrefix: name,
@@ -93,6 +93,23 @@ $.widget = function( name, base, prototype ) {
$.widget.bridge( name, $[ namespace ][ name ] );
};
+$.widget.extend = function( target ) {
+ var input = slice.call( arguments, 1 ),
+ inputIndex = 0,
+ inputLength = input.length,
+ key,
+ value;
+ for ( ; inputIndex < inputLength; inputIndex++ ) {
+ for ( key in input[ inputIndex ] ) {
+ value = input[ inputIndex ][ key ];
+ if (input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
+ target[ key ] = $.isPlainObject( value ) ? $.widget.extend( {}, target[ key ], value ) : value;
+ }
+ }
+ }
+ return target;
+};
+
$.widget.bridge = function( name, object ) {
$.fn[ name ] = function( options ) {
var isMethodCall = typeof options === "string",
@@ -101,7 +118,7 @@ $.widget.bridge = function( name, object ) {
// allow multiple hashes to be passed on init
options = !isMethodCall && args.length ?
- $.extend.apply( null, [ true, options ].concat(args) ) :
+ $.widget.extend.apply( null, [ options ].concat(args) ) :
options;
if ( isMethodCall ) {
@@ -163,7 +180,7 @@ $.Widget.prototype = {
_createWidget: function( options, element ) {
element = $( element || this.defaultElement || this )[ 0 ];
this.element = $( element );
- this.options = $.extend( true, {},
+ this.options = $.widget.extend( {},
this.options,
this._getCreateOptions(),
options );
@@ -218,7 +235,7 @@ $.Widget.prototype = {
if ( arguments.length === 0 ) {
// don't return a reference to the internal hash
- return $.extend( {}, this.options );
+ return $.widget.extend( {}, this.options );
}
if ( typeof key === "string" ) {
@@ -230,7 +247,7 @@ $.Widget.prototype = {
parts = key.split( "." );
key = parts.shift();
if ( parts.length ) {
- curOption = options[ key ] = $.extend( true, {}, this.options[ key ] );
+ curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
for ( i = 0; i < parts.length - 1; i++ ) {
curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
curOption = curOption[ parts[ i ] ];