Permalink
Browse files

Enhancer: Add new enhancer module

  • Loading branch information...
arschmitz committed May 6, 2015
1 parent 483342c commit 2f9d8f2041cde68c98f3461492faa145a50cbdb3
Showing with 296 additions and 1 deletion.
  1. +3 −1 js/index.php
  2. +53 −0 js/widgets/enhancer.backcompat.js
  3. +115 −0 js/widgets/enhancer.js
  4. +74 −0 tests/unit/enhancer/enhancer.js
  5. +51 −0 tests/unit/enhancer/index.html
View
@@ -21,9 +21,12 @@
'helpers.js',
'data.js',
'animationComplete.js',
'widgets/enhancer.js',
'widgets/enhancer.backcompat.js',
'widgets/page.js',
'widgets/page.dialog.js',
'widgets/loader.js',
'degradeInputs.js',
'events/navigate.js',
'navigation/path.js',
'navigation/base.js',
@@ -45,7 +48,6 @@
'transitions/visuals/flip.js',
'transitions/visuals/flow.js',
'transitions/visuals/turn.js',
'degradeInputs.js',
'../external/jquery-ui/accordion.js',
'widgets/accordion.js',
'widgets/dialog.js',
@@ -0,0 +1,53 @@
/*!
* jQuery Mobile Enhancer Backcompat@VERSION
* http://jquerymobile.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
//>>label: Enhancer
//>>group: Widgets
//>>description: Enables declarative initalization of widgets
//>>docs: http://api.jquerymobile.com/enhancer/
( function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define( [
"jquery",
"jquery-ui/widget",
"widgets/enhancer" ], factory );
} else {
// Browser globals
factory( jQuery );
}
} )( function( $ ) {
if ( $.mobileBackcompat !== false ) {
var originalGenerator = $.fn.enhance.initGenerator,
filter = function( elements ) {
elements = elements.not( $.mobile.keepNative );
if ( $.mobile.ignoreContentEnabled ) {
elements.each( function() {
if ( $( this ).closest( "[data-" + $.mobile.ns + "enhanced='false']" ).length ) {
elements = elements.not( this );
}
} );
}
return elements;
},
generator = function( prototype, ns ) {
return prototype.initSelector ||
$[ prototype.namespace ][ prototype.widgetName ].prototype.initSelector ||
originalGenerator( prototype, ns );
};
$.fn.enhance._filter = filter;
$.fn.enhance.initGenerator = generator;
}
} );
View
@@ -0,0 +1,115 @@
/*!
* jQuery Mobile Enhancer @VERSION
* http://jquerymobile.com
*
* Copyright jQuery Foundation and other contributors
* Released under the MIT license.
* http://jquery.org/license
*/
//>>label: Enhancer
//>>group: Widgets
//>>description: Enhables declarative initalization of widgets
//>>docs: http://api.jquerymobile.com/enhancer/
( function( factory ) {
if ( typeof define === "function" && define.amd ) {
// AMD. Register as an anonymous module.
define( [
"jquery",
"jquery-ui/widget" ], factory );
} else {
// Browser globals
factory( jQuery );
}
} )( function( $ ) {
var plugin = {
enhance: function() {
// Loop over and execute any hooks that exist
for ( var i = 0; i < $.fn.enhance.hooks.length; i++ ) {
$.fn.enhance.hooks[ i ].apply( this, arguments );
}
// Call the default enhancer function
$.fn.enhance.defaultFunction.apply( this, arguments );
return this;
}
},
getNamespace = function() {
return $.fn.enhance.ns || $.mobile.ns || "";
};
// Generate the init selector to be used by a widget
plugin.enhance.initGenerator = function( prototype, ns ) {
return "[data-" + ns + "role='" + prototype.widgetName + "']";
};
// Check if the enhancer has already been defined if it has copy its hooks if not
// define an empty array
plugin.enhance.hooks = ( $.fn.enhance && $.fn.enhance.hooks ) ? $.fn.enhance.hooks : [];
plugin.enhance._filter = $.fn.enhance ? $.fn.enhance._filter || false : false;
// Default function
plugin.enhance.defaultFunction = function() {
var that = this.addBack();
// Enhance widgets
function crawlChildren( _childConstructors ) {
$.each( _childConstructors, function( index, constructor ) {
var prototype = constructor.prototype,
found = that.find(
plugin.enhance.initGenerator( prototype, getNamespace() )
);
if ( plugin.enhance._filter ) {
found = plugin.enhance._filter( found );
}
found[ prototype.widgetName ]();
if ( constructor._childConstructors && constructor._childConstructors.length > 0 ) {
crawlChildren( constructor._childConstructors );
}
} );
}
crawlChildren( $.Widget._childConstructors );
};
// This is for backcompat remove in 1.6
plugin.enhanceWithin = function() {
return this.children().enhance();
};
$.extend( $.fn, plugin );
$.extend( $.Widget.prototype, {
_getCreateOptions: function() {
var option, value,
// Get all data at once avoid multiple lookups http://jsperf.com/jqm-data-bulk
data = this.element.data(),
options = {},
ns = getNamespace().replace( "-", "" );
// Translate data-attributes to options
for ( option in this.options ) {
value = data[ ns + (
!ns ?
option :
option.charAt( 0 ).toUpperCase() + option.slice( 1 )
) ];
if ( value !== undefined ) {
options[ option ] = value;
}
}
return options;
}
} );
return plugin;
} );
@@ -0,0 +1,74 @@
module( "enhancer: basic" );
test( "Basic widget enhancement", function() {
expect( 2 );
$( "#basic-enhance" ).enhance();
ok( $( "#basic-toolbar" ).toolbar( "instance" ),
"widgets loaded before enhancer are enhanced" );
ok( $( "#basic-flipswitch" ).flipswitch( "instance" ),
"widgets loaded after enhancer are enhanced" );
} );
test( "Custom init selector", function() {
expect( 1 );
$( "#basic-enhance" ).enhance();
ok( $( "#basic-textinput" ).textinput( "instance" ),
"Widgets work with custom initSelectors" );
} );
test( "enhanceWithin", function() {
expect( 2 );
var toolbar = $( "#enhance-within-target" ).enhanceWithin();
ok( $( "#enhance-within-input" ).textinput( "instance" ),
"enhanceWithin enhance inputs within the container" );
strictEqual( !!toolbar.toolbar( "instance" ), false,
"enhanceWithin does not enhance the parent element" );
} );
var hook;
module( "enhancer: custom hook", {
setup: function() {
hook = function() {
$( this ).find( ".hook-target" ).addClass( "hooked" );
};
$.fn.enhance.hooks.push( hook );
},
teardown: function() {
$.fn.enhance.hooks.splice( $.inArray( hook, $.fn.enhance.hooks ), 1 );
}
} );
test( "custom hook", function( assert ) {
expect( 1 );
$( "#hooks" ).enhance();
assert.hasClasses( $( ".hook-target" ), "hooked" );
} );
var generator;
module( "enhancer: custom generator", {
setup: function() {
generator = $.fn.enhance.initGenerator;
$.fn.enhance.initGenerator = function( prototype ) {
return "." + prototype.widgetName;
};
},
teardown: function() {
$.fn.enhance.initGenerator = generator;
}
} );
test( "custom generator", function( assert ) {
expect( 3 );
$( "#custom-generator" ).enhance();
ok( $( ".toolbar" ).toolbar( "instance" ), "custom generator works with toolbar" );
ok( $( ".flipswitch" ).flipswitch( "instance" ), "custom generator works with flipswitch" );
ok( $( ".textinput" ).textinput( "instance" ),
"custom generator overrides custom initSelectors" );
} );
@@ -0,0 +1,51 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>jQuery Mobile Enhancer Test Suite</title>
<script src="../../../external/requirejs/require.js"></script>
<script src="../../../js/requirejs.config.js"></script>
<script src="../../../js/jquery.tag.inserter.js"></script>
<script src="../../jquery.setNameSpace.js"></script>
<script src="../../jquery.testHelper.js"></script>
<script src="../../../external/qunit/qunit.js"></script>
<script src="../../../external/qunit-assert-classes/qunit-assert-classes.js"></script>
<script>
$.testHelper.asyncLoad([
[ "widgets/toolbar" ],
[ "widgets/enhancer" ],
[
"widgets/forms/flipswitch",
"widgets/forms/textinput"
],
[ "./enhancer.js" ]
]);
</script>
<link rel="stylesheet" href="../../../css/themes/default/jquery.mobile.css"/>
<link rel="stylesheet" href="../../../external/qunit/qunit.css"/>
<link rel="stylesheet" href="../../jqm-tests.css"/>
<script src="../../swarminject.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="basic-enhance">
<div data-role="header" id="basic-toolbar"></div>
<input type="checkbox" id="basic-flipswitch" data-role="flipswitch">
<input type="text" id="basic-textinput">
</div>
<div id="custom-generator">
<div class="toolbar" id="generator-toolbar"></div>
<input type="checkbox" class="flipswitch" id="generator-flipswitch" data-role="flipswitch">
<input type="text" class="textinput" id="generator-textinput">
</div>
<div id="hooks">
<div class="hook-target"></div>
</div>
<div data-role="header" id="enhance-within-target">
<input type="text" id="enhance-within-input">
</div>
</html>

0 comments on commit 2f9d8f2

Please sign in to comment.