Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
remybach committed Jul 1, 2012
0 parents commit e676e76
Show file tree
Hide file tree
Showing 9 changed files with 721 additions and 0 deletions.
39 changes: 39 additions & 0 deletions .gitignore
@@ -0,0 +1,39 @@
# Numerous always-ignore extensions
*.diff
*.err
*.orig
*.log
*.rej
*.swo
*.swp
*.vi
*~
*.sass-cache

# OS or Editor folders
.DS_Store
Thumbs.db
.cache
.project
.settings
.tmproj
*.esproj
nbproject
*.sublime-project
*.sublime-workspace

# Dreamweaver added files
_notes
dwsync.xml

# Komodo
*.komodoproject
.komodotools

# Folders to ignore
.hg
.svn
.CVS
intermediate
.idea
cache
21 changes: 21 additions & 0 deletions README.md
@@ -0,0 +1,21 @@
# Wordpress Live Admin Navigation Filter

Add a search box to the wordpress admin nav that allows you to more easily find that menu item you can't see at a glance.

## Installation

1. Upload the `live-admin-nav-filter` folder to your `/wp-content/plugins/` directory.
2. Activate the plugin through the `Plugins` menu in WordPress.
3. You should now see a search box below the `collapse menu` button in the admin menu.

## Features

* Quickly and easily find what you're looking for.
* Keyboard navigation friendly (hit `/` to focus the search field, use the `up` and `down` keys to select the menu item you're after, hit the `enter` key to go to the selected menu item)
* Customizable border and highlight colours.

## Screenshots

1. Example results on expanded menu item.
2. Multiple results.
3. The settings screen.
36 changes: 36 additions & 0 deletions README.txt
@@ -0,0 +1,36 @@
=== Live Admin Navigation Filter ===
Contributors: Remy Bach
Donate link: Through PayPal... remy[at]bach.me.uk
Tags: admin, nav, filter, live filter, navigation, navigation search, admin search
Requires at least: 3.2
Tested up to: 3.4.1
Stable tag: 1.0

Add a search box to the admin nav that allows you to more easily find that menu item you can't see at a glance.

== Description ==

Add a search box to the admin nav that allows you to more easily find that menu item you can't see at a glance.

== Installation ==

1. Upload the `live-admin-nav-filter` folder to your `/wp-content/plugins/` directory.
2. Activate the plugin through the `Plugins` menu in WordPress.
3. You should now see a search box below the `collapse menu` button in the admin menu.

== Features ==

* Quickly and easily find what you're looking for.
* Keyboard navigation friendly (hit `/` to focus the search field, use the `up` and `down` keys to select the menu item you're after, hit the `enter` key to go to the selected menu item)
* Customizable border and highlight colours.

== Screenshots ==

1. Example results on expanded menu item.
2. Multiple results.
3. The settings screen.

== Changelog ==

= 1.0 =
* Initial Release
71 changes: 71 additions & 0 deletions css/admin.css
@@ -0,0 +1,71 @@
.lnf-filter-bottom, .lnf-filter-top {
margin:3px;
}
.admin-bar.branch-3-2 .lnf-filter-top,
.admin-bar.branch-3-3 .lnf-filter-top {
position:relative;
top:28px;
}
/* Word Highlight */
.lnf-highlight {
background:#FFED2B;
color:#000;
display:inline-block;
text-shadow:none;
}
.lnf-focus, #adminmenu .lnf-focus .wp-submenu {
border:2px solid #FFED2B;
}
#adminmenu a.lnf-focused-item, .lnf-focused-item .lnf-highlight {
text-decoration:underline;
}
#adminmenu .lnf-focus .wp-menu-arrow,
#adminmenu .lnf-focus .wp-menu-arrow div {
display:block;
z-index:1001;
}
#adminmenu .lnf-focus .wp-menu-img {
opacity:1;

filter:alpha(opacity=100);
}
#adminmenu .lnf-focus .wp-submenu {
z-index:1000;
}
#adminmenu li .wp-submenu.lnf-sub-open, .folded #adminmenu .wp-has-current-submenu .wp-submenu.lnf-sub-open {
display:block;
}
.lnf-error {
color:#FF0000;
}

/* Admin Settings Colours */
.lnf-colour {
display:inline-block;
height:32px;
margin-right:10px;
width:32px;

-webkit-box-shadow:1px 1px 2px 0px rgba(0,0,0,0.5); /* Saf3-4, iOS 4.0.2 - 4.2, Android 2.3+ */
box-shadow:1px 1px 2px 0px rgba(0,0,0,0.5); /* Opera 10.5, IE9, FF4+, Chrome 6+, iOS 5 */

-webkit-transition:all 0.2s ease-out; /* Saf3.2+, Chrome */
-moz-transition:all 0.2s ease-out; /* FF4+ */
-o-transition:all 0.2s ease-out; /* Opera 10.5+ */
transition:all 0.2s ease-out;
}
.lnf-colour.selected {
border:1px solid black !important; /* Needs !important to override the border in the style attribute (allows for dynamic adding of colours) */
}
.lnf-colour:not(.selected) {
cursor:pointer;
}
.lnf-colour:not(.selected):hover {
height:35px;
margin-left:-3px;
margin-top:-3px;
width:35px;

-webkit-box-shadow:2px 2px 4px 0px rgba(0,0,0,0.5); /* Saf3-4, iOS 4.0.2 - 4.2, Android 2.3+ */
box-shadow:2px 2px 4px 0px rgba(0,0,0,0.5); /* Opera 10.5, IE9, FF4+, Chrome 6+, iOS 5 */
}
216 changes: 216 additions & 0 deletions js/admin.js
@@ -0,0 +1,216 @@
// lnf = live nav filter : use this in an attempt to avoid clashing with other plugins' class names.
(function($) {
jQuery(function($) {
// Add our filter field.
var filter_field = '<input type="search" placeholder="filter" id="lnf" class="lnf-filter-'+
(LNF_POSITION ? LNF_POSITION : 'bottom')+'"'+
(LNF_HIDDEN ? 'style="display:none;"' : '')+' />';

// Position this as specified in our settings
if (LNF_POSITION && LNF_POSITION === 'top') {
$('#adminmenu').before(filter_field);
} else {
$('#adminmenu').after(filter_field);
}
$('#adminmenu li > a').each(function(i, val) {
var searchable = $(this).html()
.replace(/^<.*?\/?>/, '') // Remove any html tags at the beginning of the element.
.match(/([\w\s-&;]+)/); // Lastly, search for the first words (\w\s) in the <a> (sometimes there's
// additional HTML for update counts, etc.) Let's also include dashes,
// and allow html entities (-&;)

// Don't go any further if this doesn't match
if ( !searchable || (searchable && searchable.length < 2) ) { return false; }

// Append this as a data attribute for searching later (we do this so that we can still search while the
// element has our additional highlighting markup in it).
$.data(this, 'lnf-search', searchable[1]);
});

var timer = false;
$('#lnf').keyup(function(e) {
var lnf_input = this;

// Add some latency so the menu doesn't flash when typing faster than ~60wpm...
// 60wpm / 5 (approximate average of characters per word) / 60 seconds = 0.2seconds (or 200ms)
clearTimeout(timer);
timer = setTimeout(function() {
filter.call(lnf_input, e);
}, 200);
}).change(filter);

// If the user hits '/', focus our filter field.
$(document).keyup(function(e) {
// If the user isn't trying to legitimately type & the key that was pressed matches
if ( e.keyCode === 191 && $('input:focus, textarea:focus').length === 0 ) { // 191 == /
if ( $('#lnf:hidden').length > 0 ) {
$('#lnf:hidden').slideDown(100, function() {
$(this).focus();
});
} else {
$('#lnf').focus();
}

return false;
}
});

function filter(e) {
if ( e.keyCode === 13 ) { // If the user hits enter, let's go to the selected link.
location.href = $('.lnf-focused-item').attr('href');
} else if ( e.keyCode === 40 ) { // If the user has pressed down
focus(1);
return false;
} else if ( e.keyCode === 38 ) { // If the user has pressed up
focus(-1);
return false;
} else if ( this.value && this.value.length >= 3 ) { // Make sure there's something to search for
var search = new RegExp(this.value, 'i');

// Make sure there is even something matching at all here
if ( search.test( $('#adminmenu').html() ) ) {
$('#adminmenu li > a').each(function(i, val) {
// If the text in this link matches, work our magic.
if ( !search.test( $(this).data('lnf-search') ) ) {
$(this).parent('li').fadeTo('fast', 0.15).addClass('lnf-hidden');
} else {
reset(this);
unhighlight($(this).find('.lnf-highlight'));
$(this).html(val.innerHTML.replace(search, '<mark class="lnf-highlight">'+val.innerHTML.match(search)[0]+'</mark>'));

// If this is a sub menu, show it
if ( $(this).parents('.wp-submenu').length > 0 ) {
$(this).parents('.wp-submenu').addClass('lnf-sub-open');
$(this).parents('.lnf-hidden').fadeTo('fast', 1).removeClass('lnf-hidden');
}
}
});

// Focus the first result
focus(0);

$('#lnf').removeClass('lnf-error');
} else {
reset('.lnf-hidden');
unhighlight( $('.lnf-highlight') );
$('#lnf').addClass('lnf-error');
}
} else {
if (e.keyCode === 27 && LNF_HIDDEN) { // 27 == Escape
$('#lnf').slideUp(100).blur();
}

reset('.lnf-hidden');
unhighlight( $('.lnf-highlight') );
$('#lnf').removeClass('lnf-error');
$('.lnf-sub-open').removeClass('lnf-sub-open');
$('.lnf-focused-item').removeClass('lnf-focused-item');
}
}

/**
* Reset the given element back to it's original state
* @param DOM Element what The element to reset.
*/
function reset(what) {
$(what).fadeTo('fast', 1).removeClass('lnf-hidden').parents('.lnf-focus').removeClass('lnf-focus');
$(what).parents('.lnf-focused-item').removeClass('lnf-focused-item');

$('#adminmenu .wp-submenu:visible').each(function(i, val) {
if ( $(this).hasClass('lnf-sub-open') && $(this).parent('li').find('.lnf-highlight').length === 0 ) {
$(this).removeClass('lnf-sub-open');
}
});
}

/**
* Remove the highlight wrapper from the given element.
* @param DOM Element what The element to remove all highlighting from.
*/
function unhighlight(what) {
// Remove the highlighting
$(what).each(function(i, val) {
$(this).replaceWith(this.innerHTML);
});
}

/**
* Focus the next/previous element. Has scope for selecting the first item too if none are selected yet.
* @param Number which_way Either -1 or 1 depending on whether to go to the previous or next item respectively.
*/
function focus(which_way) {
var i = 0,
highlighted = $('.lnf-highlight')
where_to = 0;

// If there isn't a focused item, make it the first one.
if ( $('.lnf-focused-item').length === 0 ) {
which_way = 0;
} else {
// Get the index of the currently focused item.
i = $.inArray( $('.lnf-focused-item .lnf-highlight')[0], highlighted );
}

// Make the selection wrap around to the beginning when hitting the end and vice versa
if ( i+which_way < 0 ) { // when pressing up on the first item.
where_to = highlighted.length-1;
} else if ( i+which_way > highlighted.length-1 ) { // when pressing down on the last item.
where_to = 0;
} else { // otherwise it's safe to go to the next/previous item.
where_to = i+which_way;
}

// Remove the currently focused item.
$('.lnf-focus, .lnf-focused-item').removeClass('lnf-focus').removeClass('lnf-focused-item');

// Add the highlight class to the li that's highest up in the dom.
var parent_lis = $( $('.lnf-highlight').get(where_to) ).parents('li');
$(parent_lis[parent_lis.length-1]).addClass('lnf-focus');
// Also indicate which is the currently selected link (so the user can see where hitting the Enter key takes them.)
$( $('.lnf-highlight').get(where_to) ).parents('a').addClass('lnf-focused-item');
}

/*===== Give the user predefined options for colours on the options page. =====*/
if ( $('#border_colour').length > 0 ) {
var colours = {
blue:'80C8F0',
green:'6EAF51',
orange:'EC6D1E',
pink:'EA6C9C',
purple:'A05DA2',
yellow:'FFED2B'
};

// Add our suggested colour swatches before the input field.
$('#border_colour, #highlight_colour').before('<div class="lnf-colour-options"/>');
$.each(colours, function(name, hex) {
$('.lnf-colour-options').each(function() {
var selected = false;
if ( $(this).next('input').val().match(hex) ) {
selected = true;
}
$(this).append(''+
'<span '+
'class="lnf-colour lnf-'+name+(selected ? ' selected' : '')+'" '+
'data-hex="'+hex+'" '+
'style="background:#'+hex+';'+(selected ? '' : 'border:1px solid #'+hex)+'" '+
'/>');
});
});

// Give the colour swatches their functionality here.
$('.lnf-colour').click(function(e) {
var current = $(this).parents('.lnf-colour-options').find('.selected');

// Update our input field.
$(this).parents('.lnf-colour-options').next('input').val( '#'+$(this).data('hex') );
// Clear the currently selected swatch
current.removeClass('selected').css('border', '1px solid #'+$(current).data('hex'));
// Indicate that this is the currently selected swatch.
$(this).addClass('selected');

e.preventDefault();
});
}
});
})(jQuery);

0 comments on commit e676e76

Please sign in to comment.