diff --git a/js/widgets/forms/textinput.js b/js/widgets/forms/textinput.js index 40d100218a1..f23c31cf354 100644 --- a/js/widgets/forms/textinput.js +++ b/js/widgets/forms/textinput.js @@ -23,133 +23,214 @@ $.widget( "mobile.textinput", $.mobile.widget, { }, _create: function() { + this._refresh(true); + }, + _refresh: function(create) { var self = this, input = this.element, o = this.options, - theme = o.theme || $.mobile.getInheritedTheme( this.element, "c" ), - themeclass = " ui-body-" + theme, - miniclass = o.mini ? " ui-mini" : "", - isSearch = input.is( "[type='search'], :jqmData(type='search')" ), - focusedEl, clearbtn, - clearBtnText = o.clearSearchButtonText || o.clearBtnText, - clearBtnBlacklist = input.is( "textarea, :jqmData(type='range')" ), - inputNeedsClearBtn = !!o.clearBtn && !clearBtnBlacklist, - inputNeedsWrap = input.is( "input" ) && !input.is( ":jqmData(type='range')" ); - + clearBtnText, + focusedEl, + miniclass, + inputNeedsClearBtn, + theme, + isSearch = input.is("[type='search'], :jqmData(type='search')"), + clearBtnBlacklist = input.is("textarea, :jqmData(type='range')"), + inputNeedsWrap = input.is("input") && !input.is(":jqmData(type='range')"); + function toggleClear() { - setTimeout( function() { - clearbtn.toggleClass( "ui-input-clear-hidden", !input.val() ); - }, 0 ); - } - - $( "label[for='" + input.attr( "id" ) + "']" ).addClass( "ui-input-text" ); - - focusedEl = input.addClass( "ui-input-text ui-body-"+ theme ); - - // XXX: Temporary workaround for issue 785 (Apple bug 8910589). - // Turn off autocorrect and autocomplete on non-iOS 5 devices - // since the popup they use can't be dismissed by the user. Note - // that we test for the presence of the feature by looking for - // the autocorrect property on the input element. We currently - // have no test for iOS 5 or newer so we're temporarily using - // the touchOverflow support flag for jQM 1.0. Yes, I feel dirty. - jblas - if ( typeof input[0].autocorrect !== "undefined" && !$.support.touchOverflow ) { - // Set the attribute instead of the property just in case there - // is code that attempts to make modifications via HTML. - input[0].setAttribute( "autocorrect", "off" ); - input[0].setAttribute( "autocomplete", "off" ); - } - - //"search" and "text" input widgets - if ( isSearch ) { - focusedEl = input.wrap( "
" ).parent(); - } else if ( inputNeedsWrap ) { - focusedEl = input.wrap( "" ).parent(); + setTimeout(function () { + clearbtn.toggleClass("ui-input-clear-hidden", !input.val()); + }, 0); } - - if( inputNeedsClearBtn || isSearch ) { - clearbtn = $( "" + clearBtnText + "" ) - .bind( "click", function( event ) { - input - .val( "" ) - .focus() - .trigger( "change" ); - clearbtn.addClass( "ui-input-clear-hidden" ); + + function buildClearBtn() { + clearbtn = $("" + clearBtnText + "") + .bind("click", function (event) { + input.val("").focus().trigger("change"); + clearbtn.addClass("ui-input-clear-hidden"); event.preventDefault(); - }) - .appendTo( focusedEl ) - .buttonMarkup({ + }).appendTo(focusedEl).buttonMarkup({ icon: "delete", iconpos: "notext", corners: true, shadow: true, mini: o.mini }); - - if ( !isSearch ) { - focusedEl.addClass( "ui-input-has-clear" ); + + if (!isSearch) { + focusedEl.addClass("ui-input-has-clear"); } toggleClear(); - input.bind( "paste cut keyup input focus change blur", toggleClear ); - } - else if ( !inputNeedsWrap && !isSearch ) { - input.addClass( "ui-corner-all ui-shadow-inset" + themeclass + miniclass ); + input.bind("paste cut keyup input focus change blur", toggleClear); } + + if (!create) { + var oldTheme, dataMini, refreshMini = false; - input.focus(function() { - // In many situations, iOS will zoom into the input upon tap, this prevents that from happening - if ( o.preventFocusZoom ) { - $.mobile.zoom.disable( true ); - } - focusedEl.addClass( $.mobile.focusClass ); - }) - .blur(function() { - focusedEl.removeClass( $.mobile.focusClass ); - if ( o.preventFocusZoom ) { - $.mobile.zoom.enable( true ); - } - }) - - // Autogrow - if ( input.is( "textarea" ) ) { - var extraLineHeight = 15, - keyupTimeoutBuffer = 100, - keyupTimeout; - - this._keyup = function() { - var scrollHeight = input[ 0 ].scrollHeight, - clientHeight = input[ 0 ].clientHeight; - - if ( clientHeight < scrollHeight ) { - input.height( scrollHeight + extraLineHeight ); + focusedEl = input; + oldTheme = o.theme || $.mobile.getInheritedTheme(input, "c"); + theme = input.attr("data-" + $.mobile.ns + "theme") || (o.theme || $.mobile.getInheritedTheme(input, "c")); + o.clearBtn = input.attr("data-" + $.mobile.ns + "clear-btn") === 'true'; + inputNeedsClearBtn = !!o.clearBtn && !clearBtnBlacklist; + + if (isSearch || inputNeedsWrap) { + focusedEl = input.parent(); + focusedEl.removeClass("ui-body-" + oldTheme).addClass("ui-body-" + theme); + } + + input.removeClass("ui-body-" + oldTheme).addClass("ui-body-" + theme); + + o.theme = theme; + + //is data-mini changed? + dataMini = input.attr("data-" + $.mobile.ns + "mini") === 'true'; + + if (o.mini !== dataMini) { + o.mini = dataMini; + refreshMini = true; + miniclass = o.mini ? "ui-mini" : ""; + focusedEl.removeClass("ui-mini").addClass(miniclass); + } + + //if textinput or search + if (inputNeedsClearBtn || isSearch) { + clearBtnText = input.attr("data-" + $.mobile.ns + "clear-btn-text"); + + //accept even an empty string + if (typeof clearBtnText === "undefined") { + clearBtnText = o.clearSearchButtonText || o.clearBtnText; + } + + clearbtn = focusedEl.find(".ui-input-clear"); + + if (!clearbtn.length) { + buildClearBtn(); + } else { + clearbtn[0].title = clearBtnText; + clearbtn.find(".ui-btn-text").text(clearBtnText); + } + + clearbtn.removeClass("ui-btn-up-" + oldTheme).addClass("ui-btn-up-" + theme); + + if (refreshMini) { + if (miniclass) { + clearbtn.removeClass("ui-fullsize").addClass(miniclass); + } else { + clearbtn.removeClass("ui-mini").addClass("ui-fullsize"); + } } - }; - input.on( "keyup change input paste", function() { - clearTimeout( keyupTimeout ); - keyupTimeout = setTimeout( self._keyup, keyupTimeoutBuffer ); + clearbtn.attr("data-theme", theme); + clearbtn.toggleClass("ui-input-clear-hidden", !input.val()); + + } else { + if (focusedEl.length) { + focusedEl.find(".ui-input-clear").remove(); + } + } + + if (input.attr("disabled")) { + this.disable(); + } else { + this.enable(); + } + } else { + theme = o.theme || $.mobile.getInheritedTheme(this.element, "c"); + themeclass = " ui-body-" + theme; + miniclass = o.mini ? " ui-mini" : ""; + inputNeedsClearBtn = !!o.clearBtn && !clearBtnBlacklist; + clearBtnText = o.clearSearchButtonText || o.clearBtnText; + + $("label[for='" + input.attr("id") + "']").addClass("ui-input-text"); + + focusedEl = input.addClass("ui-input-text ui-body-" + theme); + + // XXX: Temporary workaround for issue 785 (Apple bug 8910589). + // Turn off autocorrect and autocomplete on non-iOS 5 devices + // since the popup they use can't be dismissed by the user. Note + // that we test for the presence of the feature by looking for + // the autocorrect property on the input element. We currently + // have no test for iOS 5 or newer so we're temporarily using + // the touchOverflow support flag for jQM 1.0. Yes, I feel dirty. - jblas + if (typeof input[0].autocorrect !== "undefined" && !$.support.touchOverflow) { + // Set the attribute instead of the property just in case there + // is code that attempts to make modifications via HTML. + input[0].setAttribute("autocorrect", "off"); + input[0].setAttribute("autocomplete", "off"); + } + + //"search" and "text" input widgets + if (isSearch) { + focusedEl = input.wrap("").parent(); + } else if (inputNeedsWrap) { + focusedEl = input.wrap("").parent(); + } + + if (inputNeedsClearBtn || isSearch) { + buildClearBtn(); + } else if (!inputNeedsWrap && !isSearch) { + input.addClass("ui-corner-all ui-shadow-inset" + themeclass + miniclass); + } + + input.focus(function () { + // In many situations, iOS will zoom into the input upon tap, this prevents that from happening + if (o.preventFocusZoom) { + $.mobile.zoom.disable(true); + } + focusedEl.addClass($.mobile.focusClass); + }).blur(function () { + focusedEl.removeClass($.mobile.focusClass); + if (o.preventFocusZoom) { + $.mobile.zoom.enable(true); + } }); - // binding to pagechange here ensures that for pages loaded via - // ajax the height is recalculated without user input - this._on( $.mobile.document, { "pagechange": "_keyup" }); + // Autogrow + if (input.is("textarea")) { + var extraLineHeight = 15, + keyupTimeoutBuffer = 100, + keyupTimeout; - // Issue 509: the browser is not providing scrollHeight properly until the styles load - if ( $.trim( input.val() ) ) { - // bind to the window load to make sure the height is calculated based on BOTH - // the DOM and CSS - this._on( $.mobile.window, {"load": "_keyup"}); + this._keyup = function () { + var scrollHeight = input[0].scrollHeight, + clientHeight = input[0].clientHeight; + + if (clientHeight < scrollHeight) { + input.height(scrollHeight + extraLineHeight); + } + }; + + input.on("keyup change input paste", function () { + clearTimeout(keyupTimeout); + keyupTimeout = setTimeout(self._keyup, keyupTimeoutBuffer); + }); + + // binding to pagechange here ensures that for pages loaded via + // ajax the height is recalculated without user input + this._on($.mobile.document, { "pagechange": "_keyup" }); + + // Issue 509: the browser is not providing scrollHeight properly until the styles load + if ($.trim(input.val())) { + // bind to the window load to make sure the height is calculated based on BOTH + // the DOM and CSS + this._on($.mobile.window, { "load": "_keyup" }); + } + } + if (input.attr("disabled")) { + this.disable(); } - } - if ( input.attr( "disabled" ) ) { - this.disable(); } }, - + + refresh: function() { + this._refresh(false); + }, + disable: function() { var $el, isSearch = this.element.is( "[type='search'], :jqmData(type='search')" ),