diff --git a/jquery.mobilemenu.js b/jquery.mobilemenu.js
index e51925a..1271df6 100644
--- a/jquery.mobilemenu.js
+++ b/jquery.mobilemenu.js
@@ -1,259 +1,271 @@
-(function($){
-
- //plugin's default options
- var settings = {
- combine: true, //combine multiple menus into a single select
- groupPageText: 'Main', //optgroup's aren't selectable, make an option for it
- nested: true, //create optgroups by default
- prependTo: 'body', //insert at top of page by default
- switchWidth: 480, //width at which to switch to select, and back again
- topOptionText: 'Select a page' //default "unselected" state
- },
-
- //used to store original matched menus
- $menus,
-
- //used as a unique index for each menu if no ID exists
- menuCount = 0,
-
- //used to store unique list items for combining lists
- uniqueLinks = [];
-
-
- //go to page
- function goTo(url){
- document.location.href = url;
- }
-
- //does menu exist?
- function menuExists(){
- return ($('.mnav').length) ? true : false;
- }
-
- //validate selector's matched list(s)
- function isList($this){
- var pass = true;
- $this.each(function(){
- if(!$(this).is('ul') && !$(this).is('ol')){
- pass=false;
- }
- });
- return pass;
- }//isList()
-
-
- //function to decide if mobile or not
- function isMobile(){
- return ($(window).width() < settings.switchWidth);
- }
-
-
- //function to get text value of element, but not it's children
- function getText($item){
- return $.trim($item.clone().children('ul, ol').remove().end().text());
- }
-
- //function to check if URL is unique
- function isUrlUnique(url){
- return ($.inArray(url, uniqueLinks) === -1) ? true : false;
- }
-
-
- //function to do duplicate checking for combined list
- function checkForDuplicates($menu){
-
- $menu.find(' > li').each(function(){
-
- var $li = $(this),
- link = $li.find('a').attr('href'),
- parentLink = function(){
- if($li.parent().parent().is('li')){
- return $li.parent().parent().find('a').attr('href');
- } else {
- return null;
- }
- };
-
- //check nested
s before checking current one
- if($li.find(' ul, ol').length){
- checkForDuplicates($li.find('> ul, > ol'));
- }
-
- //remove empty UL's if any are left by LI removals
- if(!$li.find(' > ul li, > ol li').length){
- $li.find('ul, ol').remove();
- }
-
- //if parent has a link, and it's not unique, append current to the "unique parent" detected earlier
- if(!isUrlUnique(parentLink(), uniqueLinks) && isUrlUnique(link, uniqueLinks)){
- $li.appendTo(
- $menu.closest('ul#mmnav').find('li:has(a[href='+parentLink()+']):first ul')
- );
- }
-
- //otherwise, check if the current is unique, if it is, add it to the unique list
- else if(isUrlUnique(link)){
- uniqueLinks.push(link);
- }
-
- //if it isn't, remove it. Simples.
- else{
- $li.remove();
- }
-
- });
- }
-
-
- //function to combine lists into one
- function combineLists(){
-
- //create a new list
- var $menu = $('');
-
- //loop through each menu and extract the list's child items
- //then append them to the new list
- $menus.each(function(){
- $(this).children().clone().appendTo($menu);
- });
-
- //de-duplicate any repeated items
- checkForDuplicates($menu);
-
- //return new combined list
- return $menu;
-
- }//combineLists()
-
-
-
- //function to create options in the select menu
- function createOption($item, $container, text){
-
- //if no text param is passed, use list item's text, otherwise use settings.groupPageText
- if(!text){
- $(''+$.trim(getText($item))+' ').appendTo($container);
- } else {
- $(''+text+' ').appendTo($container);
- }
-
- }//createOption()
-
-
-
- //function to create option groups
- function createOptionGroup($group, $container){
-
- //create for sub-nav items
- var $optgroup = $(' ');
-
- //append top option to it (current list item's text)
- createOption($group,$optgroup, settings.groupPageText);
-
- //loop through each sub-nav list
- $group.children('ul, ol').each(function(){
-
- //loop through each list item and create an for it
- $(this).children('li').each(function(){
- createOption($(this), $optgroup);
- });
- });
-
- //append to select element
- $optgroup.appendTo($container);
-
- }//createOptionGroup()
-
-
-
- //function to create menu
- function createSelect($menu){
-
- //create to insert into the page
- var $select = $('');
- menuCount++;
-
- //create default option if the text is set (set to null for no option)
- if(settings.topOptionText){
- createOption($(''+settings.topOptionText+' '), $select);
- }
-
- //loop through first list items
- $menu.children('li').each(function(){
-
- var $li = $(this);
-
- //if nested select is wanted, and has sub-nav, add optgroup element with child options
- if($li.children('ul, ol').length && settings.nested){
- createOptionGroup($li, $select);
- }
-
- //otherwise it's a single level select menu, so build option
- else {
- createOption($li, $select);
- }
-
- });
-
- //add change event and prepend menu to set element
- $select
- .change(function(){goTo($(this).val());})
- .prependTo(settings.prependTo);
-
- }//createSelect()
-
-
- //function to run plugin functionality
- function runPlugin(){
-
- //menu doesn't exist
- if(isMobile() && !menuExists()){
-
- //if user wants to combine menus, create a single
- if(settings.combine){
- var $menu = combineLists();
- createSelect($menu);
- }
-
- //otherwise, create a select for each matched list
- else{
- $menus.each(function(){
- createSelect($(this));
- });
- }
- }
-
- //menu exists, and browser is mobile width
- if(isMobile() && menuExists()){
- $('.mnav').show();
- $menus.hide();
- }
-
- //otherwise, hide the mobile menu
- if(!isMobile() && menuExists()){
- $('.mnav').hide();
- $menus.show();
- }
-
- }//runPlugin()
-
-
-
- //plugin definition
- $.fn.mobileMenu = function(options){
-
- //override the default settings if user provides some
- if(options){$.extend(settings, options);}
-
- //check if user has run the plugin against list element(s)
- if(isList($(this))){
- $menus = $(this);
- runPlugin();
- $(window).resize(function(){runPlugin();});
- } else {
- alert('mobileMenu only works with /');
- }
-
- };//mobileMenu()
-
-})(jQuery);
+(function ($) {
+
+ //plugin's default options
+ var settings = {
+ combine: true, //combine multiple menus into a single select
+ groupPageText: 'Main', //optgroup's aren't selectable, make an option for it
+ nested: true, //create optgroups by default
+ prependTo: 'body', //insert at top of page by default
+ switchWidth: 480, //width at which to switch to select, and back again
+ topOptionText: 'Select a page' //default "unselected" state
+ },
+
+ //used to store original matched menus
+ $menus,
+
+ //used as a unique index for each menu if no ID exists
+ menuCount = 0,
+
+ //used to store unique list items for combining lists
+ uniqueLinks = [];
+
+ var mqsupport = mqSupport();
+
+ //does browser support media queries
+ //(true if mq support present)
+ //adapted from https://gist.github.com/1192923
+ function mqSupport() {
+ return !!(window.webkitMatchMedia || window.mozMatchMedia || window.oMatchMedia || window.msMatchMedia || window.matchMedia);
+ }
+
+ //go to page
+ function goTo(url){
+ document.location.href = url;
+ }
+
+ //does menu exist?
+ function menuExists(){
+ return ($('.mnav').length) ? true : false;
+ }
+
+ //validate selector's matched list(s)
+ function isList($this){
+ var pass = true;
+ $this.each(function(){
+ if(!$(this).is('ul') && !$(this).is('ol')){
+ pass=false;
+ }
+ });
+ return pass;
+ }//isList()
+
+
+ //function to decide if mobile or not
+ function isMobile() {
+ if (mqsupport == true) {
+ return (!window.matchMedia('(min-width:' + settings.switchWidth + 'px)').matches);
+ } else {
+ return ($(window).width() < settings.switchWidth);
+ }
+ }
+
+
+ //function to get text value of element, but not it's children
+ function getText($item){
+ return $.trim($item.clone().children('ul, ol').remove().end().text());
+ }
+
+ //function to check if URL is unique
+ function isUrlUnique(url){
+ return ($.inArray(url, uniqueLinks) === -1) ? true : false;
+ }
+
+
+ //function to do duplicate checking for combined list
+ function checkForDuplicates($menu){
+
+ $menu.find(' > li').each(function(){
+
+ var $li = $(this),
+ link = $li.find('a').attr('href'),
+ parentLink = function(){
+ if($li.parent().parent().is('li')){
+ return $li.parent().parent().find('a').attr('href');
+ } else {
+ return null;
+ }
+ };
+
+ //check nested s before checking current one
+ if($li.find(' ul, ol').length){
+ checkForDuplicates($li.find('> ul, > ol'));
+ }
+
+ //remove empty UL's if any are left by LI removals
+ if(!$li.find(' > ul li, > ol li').length){
+ $li.find('ul, ol').remove();
+ }
+
+ //if parent has a link, and it's not unique, append current to the "unique parent" detected earlier
+ if(!isUrlUnique(parentLink(), uniqueLinks) && isUrlUnique(link, uniqueLinks)){
+ $li.appendTo(
+ $menu.closest('ul#mmnav').find('li:has(a[href='+parentLink()+']):first ul')
+ );
+ }
+
+ //otherwise, check if the current is unique, if it is, add it to the unique list
+ else if(isUrlUnique(link)){
+ uniqueLinks.push(link);
+ }
+
+ //if it isn't, remove it. Simples.
+ else{
+ $li.remove();
+ }
+
+ });
+ }
+
+
+ //function to combine lists into one
+ function combineLists(){
+
+ //create a new list
+ var $menu = $('');
+
+ //loop through each menu and extract the list's child items
+ //then append them to the new list
+ $menus.each(function(){
+ $(this).children().clone().appendTo($menu);
+ });
+
+ //de-duplicate any repeated items
+ checkForDuplicates($menu);
+
+ //return new combined list
+ return $menu;
+
+ }//combineLists()
+
+
+
+ //function to create options in the select menu
+ function createOption($item, $container, text){
+
+ //if no text param is passed, use list item's text, otherwise use settings.groupPageText
+ if(!text){
+ $(''+$.trim(getText($item))+' ').appendTo($container);
+ } else {
+ $(''+text+' ').appendTo($container);
+ }
+
+ }//createOption()
+
+
+
+ //function to create option groups
+ function createOptionGroup($group, $container){
+
+ //create for sub-nav items
+ var $optgroup = $(' ');
+
+ //append top option to it (current list item's text)
+ createOption($group,$optgroup, settings.groupPageText);
+
+ //loop through each sub-nav list
+ $group.children('ul, ol').each(function(){
+
+ //loop through each list item and create an for it
+ $(this).children('li').each(function(){
+ createOption($(this), $optgroup);
+ });
+ });
+
+ //append to select element
+ $optgroup.appendTo($container);
+
+ }//createOptionGroup()
+
+
+
+ //function to create menu
+ function createSelect($menu){
+
+ //create to insert into the page
+ var $select = $('');
+ menuCount++;
+
+ //create default option if the text is set (set to null for no option)
+ if(settings.topOptionText){
+ createOption($(''+settings.topOptionText+' '), $select);
+ }
+
+ //loop through first list items
+ $menu.children('li').each(function(){
+
+ var $li = $(this);
+
+ //if nested select is wanted, and has sub-nav, add optgroup element with child options
+ if($li.children('ul, ol').length && settings.nested){
+ createOptionGroup($li, $select);
+ }
+
+ //otherwise it's a single level select menu, so build option
+ else {
+ createOption($li, $select);
+ }
+
+ });
+
+ //add change event and prepend menu to set element
+ $select
+ .change(function(){goTo($(this).val());})
+ .prependTo(settings.prependTo);
+
+ }//createSelect()
+
+
+ //function to run plugin functionality
+ function runPlugin(){
+ var ismobile = isMobile();
+
+ //menu doesn't exist
+ if (ismobile && !menuExists()) {
+
+ //if user wants to combine menus, create a single
+ if (settings.combine) {
+ var $menu = combineLists();
+ createSelect($menu);
+ }
+
+ //otherwise, create a select for each matched list
+ else {
+ $menus.each(function () {
+ createSelect($(this));
+ });
+ }
+ }
+
+ //menu exists, and browser is mobile width
+ if (ismobile && menuExists()) {
+ $('.mnav').show();
+ $menus.hide();
+ }
+
+ //otherwise, hide the mobile menu
+ if (!ismobile && menuExists()) {
+ $('.mnav').hide();
+ $menus.show();
+ }
+ }//runPlugin()
+
+
+
+ //plugin definition
+ $.fn.mobileMenu = function(options){
+
+ //override the default settings if user provides some
+ if(options){$.extend(settings, options);}
+
+ //check if user has run the plugin against list element(s)
+ if(isList($(this))){
+ $menus = $(this);
+ runPlugin();
+ $(window).resize(function(){runPlugin();});
+ } else {
+ alert('mobileMenu only works with /');
+ }
+
+ };//mobileMenu()
+
+})(jQuery);
diff --git a/jquery.mobilemenu.min.js b/jquery.mobilemenu.min.js
index 15854da..648b704 100644
--- a/jquery.mobilemenu.min.js
+++ b/jquery.mobilemenu.min.js
@@ -1 +1 @@
-(function(a){function f(a){document.location.href=a}function g(){return a(".mnav").length?!0:!1}function h(b){var c=!0;b.each(function(){if(!a(this).is("ul")&&!a(this).is("ol")){c=!1;}});return c}function i(){return a(window).width() li").each(function(){var c=a(this),d=c.find("a").attr("href"),f=function(){return c.parent().parent().is("li")?c.parent().parent().find("a").attr("href"):null};c.find(" ul, ol").length&&l(c.find("> ul, > ol"));c.find(" > ul li, > ol li").length||c.find("ul, ol").remove();!k(f(),e)&&k(d,e)?c.appendTo(b.closest("ul#mmnav").find("li:has(a[href="+f()+"]):first ul")):k(d)?e.push(d):c.remove()})}function m(){var b=a('');c.each(function(){a(this).children().clone().appendTo(b)});l(b);return b}function n(b,c,d){d?a(''+d+" ").appendTo(c):a(''+a.trim(j(b))+" ").appendTo(c)}function o(c,d){var e=a(' ');n(c,e,b.groupPageText);c.children("ul, ol").each(function(){a(this).children("li").each(function(){n(a(this),e)})});e.appendTo(d)}function p(c){var e=a(' ');d++;b.topOptionText&&n(a(""+b.topOptionText+" "),e);c.children("li").each(function(){var c=a(this);c.children("ul, ol").length&&b.nested?o(c,e):n(c,e)});e.change(function(){f(a(this).val())}).prependTo(b.prependTo)}function q(){if(i()&&!g())if(b.combine){var d=m();p(d)}else c.each(function(){p(a(this))});if(i()&&g()){a(".mnav").show();c.hide()}if(!i()&&g()){a(".mnav").hide();c.show()}}var b={combine:!0,groupPageText:"Main",nested:!0,prependTo:"body",switchWidth:480,topOptionText:"Select a page"},c,d=0,e=[];a.fn.mobileMenu=function(d){d&&a.extend(b,d);if(h(a(this))){c=a(this);q();a(window).resize(function(){q()})}else alert("mobileMenu only works with /")}})(jQuery);
\ No newline at end of file
+(function ($) { var settings = { combine: true, groupPageText: 'Main', nested: true, prependTo: 'body', switchWidth: 480, topOptionText: 'Select a page' }, $menus, menuCount = 0, uniqueLinks = []; var mqsupport = mqSupport(); function mqSupport() { return !!(window.webkitMatchMedia || window.mozMatchMedia || window.oMatchMedia || window.msMatchMedia || window.matchMedia) } function goTo(url) { document.location.href = url } function menuExists() { return ($('.mnav').length) ? true : false } function isList($this) { var pass = true; $this.each(function () { if (!$(this).is('ul') && !$(this).is('ol')) { pass = false } }); return pass } function isMobile() { if (mqsupport == true) { return (!window.matchMedia('(min-width:' + settings.switchWidth + 'px)').matches) } else { return ($(window).width() < settings.switchWidth) } } function getText($item) { return $.trim($item.clone().children('ul, ol').remove().end().text()) } function isUrlUnique(url) { return ($.inArray(url, uniqueLinks) === -1) ? true : false } function checkForDuplicates($menu) { $menu.find(' > li').each(function () { var $li = $(this), link = $li.find('a').attr('href'), parentLink = function () { if ($li.parent().parent().is('li')) { return $li.parent().parent().find('a').attr('href') } else { return null } }; if ($li.find(' ul, ol').length) { checkForDuplicates($li.find('> ul, > ol')) } if (!$li.find(' > ul li, > ol li').length) { $li.find('ul, ol').remove() } if (!isUrlUnique(parentLink(), uniqueLinks) && isUrlUnique(link, uniqueLinks)) { $li.appendTo($menu.closest('ul#mmnav').find('li:has(a[href=' + parentLink() + ']):first ul')) } else if (isUrlUnique(link)) { uniqueLinks.push(link) } else { $li.remove() } }) } function combineLists() { var $menu = $(''); $menus.each(function () { $(this).children().clone().appendTo($menu) }); checkForDuplicates($menu); return $menu } function createOption($item, $container, text) { if (!text) { $('' + $.trim(getText($item)) + ' ').appendTo($container) } else { $('' + text + ' ').appendTo($container) } } function createOptionGroup($group, $container) { var $optgroup = $(' '); createOption($group, $optgroup, settings.groupPageText); $group.children('ul, ol').each(function () { $(this).children('li').each(function () { createOption($(this), $optgroup) }) }); $optgroup.appendTo($container) } function createSelect($menu) { var $select = $(''); menuCount++; if (settings.topOptionText) { createOption($('' + settings.topOptionText + ' '), $select) } $menu.children('li').each(function () { var $li = $(this); if ($li.children('ul, ol').length && settings.nested) { createOptionGroup($li, $select) } else { createOption($li, $select) } }); $select.change(function () { goTo($(this).val()) }).prependTo(settings.prependTo) } function runPlugin() { var ismobile = isMobile(); if (ismobile && !menuExists()) { if (settings.combine) { var $menu = combineLists(); createSelect($menu) } else { $menus.each(function () { createSelect($(this)) }) } } if (ismobile && menuExists()) { $('.mnav').show(); $menus.hide() } if (!ismobile && menuExists()) { $('.mnav').hide(); $menus.show() } } $.fn.mobileMenu = function (options) { if (options) { $.extend(settings, options) } if (isList($(this))) { $menus = $(this); runPlugin(); $(window).resize(function () { runPlugin() }) } else { alert('mobileMenu only works with /') } } })(jQuery);
\ No newline at end of file
diff --git a/readme.md b/readme.md
index 3a2a8b0..381e667 100644
--- a/readme.md
+++ b/readme.md
@@ -1,5 +1,11 @@
# jQuery Responsive Menu Plugin
-A Plugin which turns your site's navigation into a dropdown (<`select>`) when your browser is at mobile widths.
+A Plugin which turns your site's navigation into a dropdown (``) when your browser is at mobile widths.
+
+##Changelog
+1. Added support for target="_blank" on links in the menu. This can be turned off by setting honorTargetBlank to false.
+2. Added support for window.matchMedia(). It now defaults to this and falls back to the comparing switchWidth to $(window).width() because of the differences in the way Firefox and IE10 implement .width() vs. all media queries. IE8 doesn't support window.matchMedia(), but that's OK because it measures .width() the same way as media queries.
+3. Changed the way the top level menu items are converted into links with the text from groupPageText. If that top level menu item doesn't contain a link (which it shouldn't due to touch devices), then it doesn't create the "dummy" ``.
+4. Minor speed enhancements.
## Options
The options available for the plugin are listed below.
@@ -31,6 +37,9 @@ Sets the very first ` `'s display text.
Setting this to NULL will prevent it from displaying
['string'/null]
+### honorTargetBlank [true] **new
+Carry over the functionality of any target="_blank" that you've put on your menu links.
+
## Usage
The plugin can be used like any other jQuery plugin: