1(function($){ 2 3 //plugin's default options 4 var settings = { 5 combine: true, //combine multiple menus into a single select 6 groupPageText: 'Main', //optgroup's aren't selectable, make an option for it 7 nested: true, //create optgroups by default 8 prependTo: 'body', //insert at top of page by default 9 switchWidth: 480, //width at which to switch to select, and back again 10 topOptionText: 'Select a page' //default "unselected" state 11 }, 12 13 //used to store original matched menus 14 $menus, 15 16 //used as a unique index for each menu if no ID exists 17 menuCount = 0, 18 19 //used to store unique list items for combining lists 20 uniqueLinks = []; 21 22 23 //go to page 24 function goTo(url){ 25 document.location.href = url; 26 } 27 28 //does menu exist? 29 function menuExists(){ 30 return ($('.mnav').length) ? true : false; 31 } 32 33 //validate selector's matched list(s) 34 function isList($this){ 35 var pass = true; 36 $this.each(function(){ 37 if(!$(this).is('ul') && !$(this).is('ol')){ 38 pass=false; 39 } 40 }); 41 return pass; 42 }//isList() 43 44 45 //function to decide if mobile or not 46 function isMobile(){ 47 return ($(window).width() < settings.switchWidth); 48 } 49 50 51 //function to get text value of element, but not it's children 52 function getText($item){ 53 54 var $clone_item = $item.clone(); 55 56 try 57 { 58 $clone_item.children('a').children('span.sf-description').remove(); 59 } 60 catch(err) 61 { 62 //Handle errors here 63 } 64 65 return $.trim($clone_item.children('ul, ol').remove().end().text()); 66 //return $.trim($item.clone().children('ul, ol').remove().end().text()); 67 } 68 69 //function to check if URL is unique 70 function isUrlUnique(url){ 71 return ($.inArray(url, uniqueLinks) === -1) ? true : false; 72 } 73 74 75 //function to do duplicate checking for combined list 76 function checkForDuplicates($menu){ 77 78 $menu.find(' > li').each(function(){ 79 80 var $li = $(this), 81 link = $li.find('a').attr('href'), 82 parentLink = function(){ 83 if($li.parent().parent().is('li')){ 84 return $li.parent().parent().find('a').attr('href'); 85 } else { 86 return null; 87 } 88 }; 89 90 //check nested <li>s before checking current one 91 if($li.find(' ul, ol').length){ 92 checkForDuplicates($li.find('> ul, > ol')); 93 } 94 95 //remove empty UL's if any are left by LI removals 96 if(!$li.find(' > ul li, > ol li').length){ 97 $li.find('ul, ol').remove(); 98 } 99 100 //if parent <li> has a link, and it's not unique, append current <li> to the "unique parent" detected earlier 101 if(!isUrlUnique(parentLink(), uniqueLinks) && isUrlUnique(link, uniqueLinks)){ 102 $li.appendTo( 103 $menu.closest('ul#mmnav').find('li:has(a[href='+parentLink()+']):first ul') 104 ); 105 } 106 107 //otherwise, check if the current <li> is unique, if it is, add it to the unique list 108 else if(isUrlUnique(link)){ 109 uniqueLinks.push(link); 110 } 111 112 //if it isn't, remove it. Simples. 113 else{ 114 $li.remove(); 115 } 116 117 }); 118 } 119 120 121 //function to combine lists into one 122 function combineLists(){ 123 124 //create a new list 125 var $menu = $('<ul id="mmnav" />'); 126 127 //loop through each menu and extract the list's child items 128 //then append them to the new list 129 $menus.each(function(){ 130 $(this).children().clone().appendTo($menu); 131 }); 132 133 //de-duplicate any repeated items 134 checkForDuplicates($menu); 135 136 //return new combined list 137 return $menu; 138 139 }//combineLists() 140 141 142 143 //function to create options in the select menu 144 function createOption($item, $container, text){ 145 146 //if no text param is passed, use list item's text, otherwise use settings.groupPageText 147 if(!text){ 148 $('<option value="'+$item.find('a:first').attr('href')+'">'+$.trim(getText($item))+'</option>').appendTo($container); 149 } else { 150 $('<option value="'+$item.find('a:first').attr('href')+'">'+text+'</option>').appendTo($container); 151 } 152 153 }//createOption() 154 155 156 157 //function to create option groups 158 function createOptionGroup($group, $container){ 159 160 //create <optgroup> for sub-nav items 161 var $optgroup = $('<optgroup label="'+$.trim(getText($group))+'" />'); 162 163 //append top option to it (current list item's text) 164 createOption($group,$optgroup, settings.groupPageText); 165 166 //loop through each sub-nav list 167 $group.children('ul, ol').each(function(){ 168 169 //loop through each list item and create an <option> for it 170 $(this).children('li').each(function(){ 171 createOption($(this), $optgroup); 172 }); 173 }); 174
175 //append to select element 176 $optgroup.appendTo($container); 177 178 }//createOptionGroup() 179 180 181 182 //function to create <select> menu 183 function createSelect($menu){ 184 185 //create <select> to insert into the page 186 var $select = $('<select id="mm'+menuCount+'" class="mnav" />'); 187 menuCount++; 188 189 //create default option if the text is set (set to null for no option) 190 if(settings.topOptionText){ 191 createOption($('<li>'+settings.topOptionText+'</li>'), $select); 192 } 193 194 //loop through first list items 195 $menu.children('li').each(function(){ 196 197 var $li = $(this); 198 199 //if nested select is wanted, and has sub-nav, add optgroup element with child options 200 if($li.children('ul, ol').length && settings.nested){ 201 createOptionGroup($li, $select); 202 } 203 204 //otherwise it's a single level select menu, so build option 205 else { 206 createOption($li, $select); 207 } 208 209 }); 210 211 //add change event and prepend menu to set element 212 $select 213 .change(function(){goTo($(this).val());}) 214 .prependTo(settings.prependTo); 215 216 }//createSelect() 217 218 219 //function to run plugin functionality 220 function runPlugin(){ 221 222 //menu doesn't exist 223 if(isMobile() && !menuExists()){ 224 225 //if user wants to combine menus, create a single <select> 226 if(settings.combine){ 227 var $menu = combineLists(); 228 createSelect($menu); 229 } 230 231 //otherwise, create a select for each matched list 232 else{ 233 $menus.each(function(){ 234 createSelect($(this)); 235 }); 236 } 237 } 238 239 //menu exists, and browser is mobile width 240 if(isMobile() && menuExists()){ 241 $('.mnav').show(); 242 $menus.hide(); 243 } 244 245 //otherwise, hide the mobile menu 246 if(!isMobile() && menuExists()){ 247 $('.mnav').hide(); 248 $menus.show(); 249 } 250 251 }//runPlugin() 252 253 254 255 //plugin definition 256 $.fn.mobileMenu = function(options){ 257 258 //override the default settings if user provides some 259 if(options){$.extend(settings, options);} 260 261 //check if user has run the plugin against list element(s) 262 if(isList($(this))){ 263 $menus = $(this); 264 runPlugin(); 265 $(window).resize(function(){runPlugin();}); 266 } else { 267 alert('mobileMenu only works with <ul>/<ol>'); 268 } 269 270 };//mobileMenu() 271 272})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.