|
| 1 | +$( function( $ ) { |
| 2 | + var host = "http://jquerymobile.com/amd-builder", |
| 3 | + dependencyMap, |
| 4 | + builderhtml = [], |
| 5 | + sortable = [], |
| 6 | + groupBy = function( data, iterator ) { |
| 7 | + var res = {}; |
| 8 | + |
| 9 | + _.each( _.uniq( _.map( data, iterator ) ), function( val ) { |
| 10 | + res[val] = {}; |
| 11 | + }); |
| 12 | + |
| 13 | + _.each( data, function( value, key, list ) { |
| 14 | + if ( value.group ) { |
| 15 | + res[ value.group ][ key ] = value; |
| 16 | + } else { |
| 17 | + res.Other[ key ] = value; |
| 18 | + } |
| 19 | + }); |
| 20 | + return res; |
| 21 | + }, |
| 22 | + module2domId = function( module ) { |
| 23 | + return module.replace( /\./g, '-' ) |
| 24 | + .replace( /^(.)/, function( c ) { return c.toLowerCase(); } ) |
| 25 | + .replace( /\//g, '-slash-' ); |
| 26 | + }, |
| 27 | + domId2module = function( domId ) { |
| 28 | + return domId.replace( /-slash-/g, '/' ) |
| 29 | + .replace( /\-/g, '.' ); |
| 30 | + }, |
| 31 | + group2domId = function( group ) { |
| 32 | + return group.replace( / /g, '-' ).replace( /^(.)/, function( c ) { return c.toLowerCase(); } ); |
| 33 | + }, |
| 34 | + strip = function( file ) { |
| 35 | + return file.replace( /^\.\//g, '' ).replace( /\./g, '-' ); |
| 36 | + }, |
| 37 | + buildForm = function( data ) { |
| 38 | + var $form = $( "#builder" ).empty(), |
| 39 | + groupedComponents = groupBy( data, function( o, key ) { |
| 40 | + return ( o.group || "Other" ); |
| 41 | + }), |
| 42 | + groups = _.keys( groupedComponents ).sort(); |
| 43 | + |
| 44 | + _.forEach( groups, function( group ) { |
| 45 | + if ( group !== "exclude" ) { |
| 46 | + var $group = $( "<ul>" ).attr( "id", group2domId( group ) ), |
| 47 | + catlength = 0, |
| 48 | + cat, |
| 49 | + components = _.keys( groupedComponents[ group ] ).sort(); |
| 50 | + |
| 51 | + _.forEach( components, function( name ) { |
| 52 | + var id = module2domId( name ), |
| 53 | + label = data[ name ].label, |
| 54 | + desc = data[ name ].description, |
| 55 | + req = data[ name ].required, |
| 56 | + labelm = "<label for='" + id + "'>" + label + "</label>", |
| 57 | + inputm = "<input type='checkbox' class='inc' id='" + id + "' name='" + id + "'" + ( req ? " checked='checked' disabled='true'" : "") + "/>", |
| 58 | + descm = "<p class='desc'>" + desc + "</p>", |
| 59 | + item = inputm; |
| 60 | + |
| 61 | + if ( label ) { |
| 62 | + item = item + labelm; |
| 63 | + if ( desc ) { item = item + descm; } |
| 64 | + |
| 65 | + $group.append( "<li>" + item + "</li>" ); |
| 66 | + catlength++; |
| 67 | + } |
| 68 | + }); |
| 69 | + |
| 70 | + if( catlength ) { |
| 71 | + cat = $("<div class='group'></div>") |
| 72 | + .append( "<label class='select-all'> Select all <input type='checkbox' class='sel-all' name='select-all-" + group + "' /></label> <h3 class='hed-cat'>" + group + "</h3>" ) |
| 73 | + .append( $group ); |
| 74 | + |
| 75 | + $form.append( cat ); |
| 76 | + } |
| 77 | + } |
| 78 | + }); |
| 79 | + |
| 80 | + // trace dependencies for required modules and disable their dependencies |
| 81 | + $form.find( "input:checkbox:disabled:checked" ).each( |
| 82 | + function() { |
| 83 | + _.each( buildCheckListFor( domId2module( $( this ).attr( "id" ) ) ), |
| 84 | + function( module ) { |
| 85 | + $( "#"+module2domId(module) ) |
| 86 | + .prop( "checked", true ) |
| 87 | + .trigger( "change" ) |
| 88 | + .attr( "disabled", true ); |
| 89 | + } |
| 90 | + ); |
| 91 | + } |
| 92 | + ); |
| 93 | + |
| 94 | + $form.append( '<input type="submit" value="Build My Download" class="buildBtn">' ).removeClass( "loading" ); |
| 95 | + }, |
| 96 | + buildCheckListFor = function( id, hash ) { |
| 97 | + var module = dependencyMap[ id ]; |
| 98 | + hash = hash || {}; |
| 99 | + if ( module && module.deps ) { |
| 100 | + _.each( module.deps, function( name, index ) { |
| 101 | + if ( !( name in hash) ) { |
| 102 | + hash[ name ] = true; |
| 103 | + buildCheckListFor( name, hash ); |
| 104 | + } |
| 105 | + }); |
| 106 | + } |
| 107 | + return _.keys( hash ); |
| 108 | + }, |
| 109 | + buildUncheckListFor = function( id, hash ) { |
| 110 | + hash = hash || {}; |
| 111 | + _.each( dependencyMap, function( module, name ) { |
| 112 | + if ( !( name in hash ) ) { |
| 113 | + if ( _.indexOf( module.deps, id ) > -1 ) { |
| 114 | + hash[ name ] = true; |
| 115 | + buildUncheckListFor( name, hash ); |
| 116 | + } |
| 117 | + } |
| 118 | + }); |
| 119 | + return _.keys( hash ); |
| 120 | + }, |
| 121 | + resolveDependencies = function( e ) { |
| 122 | + var $el = $( e.target ), |
| 123 | + key, i, |
| 124 | + id = domId2module( $el.attr( 'id' ) ), |
| 125 | + dep = dependencyMap[ id ], |
| 126 | + checked = $el.is( ':checked' ), |
| 127 | + list; |
| 128 | + |
| 129 | + if ( checked ) { |
| 130 | + list = buildCheckListFor( id ); |
| 131 | + _.each( list, function( name ) { |
| 132 | + $( '#' + module2domId( name ) ).attr( 'checked', 'checked' ); |
| 133 | + }); |
| 134 | + } else { |
| 135 | + list = buildUncheckListFor( id ); |
| 136 | + _.each( list, function( name ) { |
| 137 | + $( '#' + module2domId( name ) ).removeAttr( 'checked' ); |
| 138 | + }); |
| 139 | + } |
| 140 | + }, |
| 141 | + selectAll = function( e ) { |
| 142 | + var $el = $( e.target ), |
| 143 | + elval = $el.prop( "checked" ); |
| 144 | + |
| 145 | + $el.closest( ".group" ).find( "ul input:checkbox" ).not( ":disabled" ).prop( "checked", elval ).trigger( "change" ); |
| 146 | + }, |
| 147 | + refreshForm = function() { |
| 148 | + var branch = $( "#branch option:selected" ).val() || "master"; |
| 149 | + $.getJSON( host + '/v1/dependencies/jquery/jquery-mobile/' + branch + '/?baseUrl=js' ).done( |
| 150 | + function( data ) { |
| 151 | + dependencyMap = data; |
| 152 | + // Clean up deps attr from relative paths and plugins |
| 153 | + _.each( dependencyMap, function( value, key, map ) { |
| 154 | + if ( value.group && value.group === "exclude" ) { |
| 155 | + delete map[ key ]; |
| 156 | + } else if ( value.deps ) { |
| 157 | + _.each( value.deps, function( v, k, m ) { |
| 158 | + m[ k ] = m[ k ].replace( /^.*!/, "" ); // remove the plugin part |
| 159 | + m[ k ] = m[ k ].replace( /\[.*$/, "" ); // remove the plugin arguments at the end of the path |
| 160 | + m[ k ] = m[ k ].replace( /^\.\//, "" ); // remove the relative path "./" |
| 161 | + }); |
| 162 | + } |
| 163 | + }); |
| 164 | + buildForm( dependencyMap ); |
| 165 | + } |
| 166 | + ); |
| 167 | + }, |
| 168 | + refreshImageBundleLink = function() { |
| 169 | + var branch = $( "#branch option:selected" ).val(), |
| 170 | + url = "http://code.jquery.com/mobile/" + branch + "/jquery.mobile.images-" + branch + ".zip"; |
| 171 | + |
| 172 | + if ( branch === "master" ) { |
| 173 | + url = "https://github.com/jquery/jquery-mobile/tree/master/css/themes/default/images"; |
| 174 | + } |
| 175 | + |
| 176 | + $( "a#imageBundleLink" ).attr( "href", url ); |
| 177 | + }, |
| 178 | + isGreaterThan = function( ref, numVer ) { |
| 179 | + return ( parseInt( ref.replace( /\./g, "" ), 10 ) > numVer ); |
| 180 | + }, |
| 181 | + isLessThan = function( ref, numVer ) { |
| 182 | + return ( parseInt( ref.replace( /\./g, "" ), 10 ) < numVer ); |
| 183 | + }; |
| 184 | + |
| 185 | + refreshForm(); |
| 186 | + refreshImageBundleLink(); |
| 187 | + |
| 188 | + $( document ) |
| 189 | + .delegate( '.inc', 'change', resolveDependencies ) |
| 190 | + .delegate( '.inc', 'click', function( e ) { |
| 191 | + $( e.target ).closest( ".group" ).find( ".sel-all" ).prop( "checked", false ); |
| 192 | + }) |
| 193 | + .delegate( '.sel-all', 'change', selectAll ); |
| 194 | + |
| 195 | + $( '#branch' ).change( refreshForm ); |
| 196 | + $( '#branch' ).change( refreshImageBundleLink ); |
| 197 | + |
| 198 | + $( "#builder" ).bind( 'submit', |
| 199 | + function( e ) { |
| 200 | + var $el = $( this ), |
| 201 | + formData = $el.find( ':checkbox[id]:checked' ), |
| 202 | + ref = $( "#branch option:selected" ).val() || "master", |
| 203 | + $button = $( e.target ).find( "input[type=submit]" ), |
| 204 | + exclude = [ "jquery", "json", "json!../package.json" ], |
| 205 | + config; |
| 206 | + |
| 207 | + $button.attr( "disabled", true ); |
| 208 | + e.preventDefault(); |
| 209 | + e.stopImmediatePropagation(); |
| 210 | + |
| 211 | + if ( isLessThan( ref, 140 ) && isGreaterThan( ref, 130 ) ) { |
| 212 | + // in 1.3.1 we added the path to requirejs plugins to the path config |
| 213 | + exclude = [ "jquery", "json", "depend", "json!../package.json" ]; |
| 214 | + } else if ( isLessThan( ref, 130 ) && isGreaterThan( ref, 120 ) ) { |
| 215 | + exclude = [ "jquery", "text", "depend", "text!../version.txt" ]; |
| 216 | + } else if ( ref.indexOf( "1.1" ) === 0 ) { |
| 217 | + exclude = [ "jquery","../external/requirejs/order", "../external/requirejs/depend", "../external/requirejs/text", "../external/requirejs/text!../version.txt" ]; |
| 218 | + } |
| 219 | + |
| 220 | + config = { |
| 221 | + baseUrl: "js", |
| 222 | + include: formData.map( function() { return domId2module( $( this ).attr( 'id' ) ); } ).toArray().join( "," ), |
| 223 | + // The excludes need to be kept in sync with the ones in jQM's Makefile |
| 224 | + exclude: exclude.join( "," ), |
| 225 | + wrap: JSON.stringify({ |
| 226 | + startFile: "build/wrap.start", |
| 227 | + endFile: "build/wrap.end" |
| 228 | + }), |
| 229 | + pragmasOnSave: '{ "jqmBuildExclude": true }', |
| 230 | + preserveLicenseComments: false, |
| 231 | + skipModuleInsertion: true, |
| 232 | + filter: "../build/filter" |
| 233 | + }; |
| 234 | + |
| 235 | + if ( isGreaterThan( ref, 130 ) || ref === "master") { |
| 236 | + // Starting at 1.3.1 we use requirejs.config.js |
| 237 | + $.extend( config, { |
| 238 | + mainConfigFile: "js/requirejs.config.js" |
| 239 | + }); |
| 240 | + } |
| 241 | + |
| 242 | + $( "#download" ).html( |
| 243 | + $( "<iframe>" ) |
| 244 | + .attr( "src", host + '/v1/bundle/jquery/jquery-mobile/' + ref + '/jquery.mobile.custom.zip?' + $.param( config ) ) |
| 245 | + ); |
| 246 | + |
| 247 | + // I could not leverage iframe.onload to re-enable the button :-/ |
| 248 | + setTimeout( function() { |
| 249 | + $button.attr( "disabled", false ); |
| 250 | + }, 1000 ); |
| 251 | + }); |
| 252 | +}); |
0 commit comments