//(c) W-Shadow
function escapeJS (s) {
s = s + '';
return s.replace(/&/g,'&').replace(/>/g,'>').replace(/ .ws_container',
cursor: 'move',
dropOnEmpty: true,
});
//Highlight the clicked menu item and show it's submenu
$('.ws_item_head').click(function () {
var p = $(this).parent();
//Highlight the active item
p.siblings().removeClass('ws_active');
p.addClass('ws_active');
//Show the appropriate submenu
if (p.hasClass('ws_menu')) {
$('.ws_submenu:visible').hide();
$('#'+p.attr('submenu_id')).show();
}
});
//Expand/collapse a menu item
$('.ws_edit_link').click(function () {
var box = $(this).parent().parent().find('.ws_editbox');
$(this).toggleClass('ws_edit_link_expanded');
//show/hide the editbox
if ($(this).hasClass('ws_edit_link_expanded')){
box.show();
} else {
//Make sure changes are applied before the menu is collapsed
box.find('input').change();
box.hide();
}
});
//The "Default" button : Reset to default value when clicked
$('.ws_reset_button').click(function () {
//Find the related input field
var field = $(this).siblings('input');
if (field.length > 0) {
//Set the value to the default
field.val(field.attr('default'));
field.addClass('ws_input_default');
//Trigget the change event to ensure consistency
field.change();
}
});
//When a field is edited, change it's appearance if it's contents don't match the default value.
$('.ws_edit_field input[type="text"]').change(function () {
if ( $(this).attr('default') != $(this).val() ) {
$(this).removeClass('ws_input_default');
}
//If the changed field is the menu title, update the header
if ( $(this).parent().attr('field_name')=='menu_title' ){
$(this).parent().parent().parent().find('.ws_item_title').html($(this).val()+' ');
}
});
//When the "Custom" checkbox is clicked, add/remove the ws_custom_item class to
//the menu (or menu item) in question.
$('.ws_custom_toggle').change(function(){
//Find the container
var my_container = $(this).parents('.ws_container:first');
if ( $(this).is(':checked') ){
addMenuFlag(my_container, 'custom_item');
} else {
removeMenuFlag(my_container, 'custom_item');
}
});
}
function outputTopMenu(menu, filename, ind){
id = 'topmenu-'+ind;
submenu_id = 'submenu-'+ind;
var subclass = '';
if ( menu.separator ) {
subclass = subclass + ' ws_menu_separator';
}
//Create the menu HTML
var s = '
';
var menu_obj = $(s).appendTo('#ws_menu_box');
//Apply flags based on the item's state
if (menu.missing && !menu.custom) {
addMenuFlag(menu_obj, 'missing');
}
if (menu.hidden) {
addMenuFlag(menu_obj, 'hidden');
}
if (menu.unused) {
addMenuFlag(menu_obj, 'unused');
}
if (menu.custom) {
addMenuFlag(menu_obj, 'custom_item');
}
//Create a container for menu items, even if there are none
$('#ws_submenu_box').append('');
//Only show menus that have items.
//Skip arrays (with a length) because filled menus are encoded as custom objects ().
if (menu.items && (typeof menu.items != 'Array')){
var i = 0;
for (var item_file in menu.items){
outputMenuEntry(menu.items[item_file], i, submenu_id);
i++;
}
}
}
function outputMenuEntry(entry, ind, parent){
if (!entry.defaults) return;
var item = $(
'
'
).appendTo('#'+parent)
//Apply flags based on the item's state
if (entry.missing && !entry.custom) {
addMenuFlag(item, 'missing');
}
if (entry.hidden) {
addMenuFlag(item, 'hidden');
}
if (entry.unused) {
addMenuFlag(item, 'unused');
}
if (entry.custom) {
addMenuFlag(item, 'custom_item');
}
}
function buildEditboxField(entry, field_name, field_caption){
if (entry[field_name]===undefined) {
return ''; //skip fields this entry doesn't have
}
return '
' + (field_caption) + ' ' +
''+
'[default]
';
}
function buildEditboxFields(entry){
var fields = {
'menu_title' : "Menu title",
'page_title' : "Page title",
'access_level' : 'Access level',
'file' : 'File',
'css_class' : 'CSS class',
'hookname' : 'CSS ID',
'icon_url' : 'Icon URL'
};
var s = '';
for (var field_name in fields){
s = s + buildEditboxField(entry, field_name, fields[field_name]);
}
//Add the "Custom item" checkbox
var is_custom = false;
if ( typeof(entry['custom']) != 'undefined' ){
is_custom = entry['custom'];
}
s = s +
'
'+
''+
'
';
return s;
}
//Encode the current menu structure as JSON
function encodeMenuAsJSON(){
var data = {};
var separator_count = 0;
var menu_position = 0;
//Iterate over all menus
$('#ws_menu_box .ws_menu').each(function(i) {
var menu_obj = {};
menu_obj.defaults = {};
menu_position++;
menu_obj.position = menu_position;
menu_obj.defaults.position = menu_position; //the real default value will later overwrite this
var filename = $(this).find('.ws_edit_field[field_name="file"] input').val();
//Check if this is a separator
if ( $(this).hasClass('ws_menu_separator') ){
menu_obj.separator = true;
if ( filename=='' ) {
filename = 'separator_'+separator_count+'_';
}
separator_count++;
}
//Iterate over all fields of the menu
$(this).find('.ws_edit_field').each(function() {
//Get the name of this field
field_name = $(this).attr('field_name');
//Skip if unnamed
if (!field_name) return true;
input_box = $(this).find('input');
//Save null if default used, custom value otherwise
if (input_box.hasClass('ws_input_default')){
menu_obj[field_name] = null;
} else {
menu_obj[field_name] = input_box.val();
}
menu_obj.defaults[field_name]=input_box.attr('default');
});
//Check if the menu is hidden
menu_obj.hidden = $(this).hasClass('ws_hidden');
//Check if this is a custom menu
menu_obj.custom = $(this).hasClass('ws_custom_item');
menu_obj.items = {};
var item_position = 0;
//Iterate over the menu's items, if any
$('#'+$(this).attr('submenu_id')).find('.ws_item').each(function (i) {
var filename = $(this).find('.ws_edit_field[field_name="file"] input').val();
var item = {};
item.defaults = {};
//Save the position data (probably not all that useful)
item_position++;
item.position = item_position;
item.defaults.position = item_position;
//Iterate over all fields of the item
$(this).find('.ws_edit_field').each(function() {
//Get the name of this field
field_name = $(this).attr('field_name');
//Skip if unnamed
if (!field_name) return true;
input_box = $(this).find('input');
//Save null if default used, custom value otherwise
if (input_box.hasClass('ws_input_default')){
item[field_name] = null;
} else {
item[field_name] = input_box.val();
}
item.defaults[field_name]=input_box.attr('default');
});
//Check if the item is hidden
if ($(this).hasClass('ws_hidden')){
item.hidden = true;
}
//Check if this is a custom item
item.custom = $(this).hasClass('ws_custom_item');
//Save the item in the parent menu
menu_obj.items[filename] = item;
});
//*/
//Attach the menu to the main struct
data[filename] = menu_obj;
});
return $.toJSON(data);
}
var item_flags = {
'custom_item' : 'This is a custom menu item',
'unused' : 'This item was automatically (re)inserted into your custom menu because it is present in the default WordPress menu',
'missing' : 'This item is not present in the default WordPress menu. Tick the "Custom" checkbox if you want it to be visible anyway.',
'hidden' : 'This item is hidden'
}
//These function manipulate the menu flags (e.g. hidden, custom, etc)
function addMenuFlag(item, flag){
item = $(item);
var item_class = 'ws_' + flag;
var img_class = 'ws_' + flag + '_flag';
item.addClass(item_class);
//Add the flag image
var flag_container = item.find('.ws_flag_container');
if ( flag_container.find('.' + img_class).length == 0 ){
flag_container.append('');
}
}
function removeMenuFlag(item, flag){
item = $(item);
var item_class = 'ws_' + flag;
var img_class = 'ws_' + flag + '_flag';
item.removeClass('ws_' + flag);
item.find('.' + img_class).remove();
}
function toggleMenuFlag(item, flag){
if (menuHasFlag(item, flag)){
removeMenuFlag(item, flag);
} else {
addMenuFlag(item, flag);
}
}
function menuHasFlag(item, flag){
return $(item).hasClass('ws_'+flag);
}
function clearMenuFlags(item){
item = $(item);
item.find('.ws_flag').remove();
for(var flag in item_flags){
item.removeClass('ws_'+flag);
}
}
//Cut & paste stuff
var menu_in_clipboard = null;
var submenu_in_clipboard = null;
var item_in_clipboard = null;
var ws_paste_count = 0;
$(document).ready(function(){
//Show the default menu
outputWpMenu(customMenu);
//Make the top menu box sortable (we only need to do this once)
$('#ws_menu_box').sortable({
items: '> .ws_container',
cursor: 'move',
dropOnEmpty: true,
});
//===== Toolbar buttons =======
//Show/Hide menu
$('#ws_hide_menu').click(function () {
//Get the selected menu
var selection = $('#ws_menu_box .ws_active');
if (!selection.length) return;
//Mark the menu as hidden/visible
//selection.toggleClass('ws_hidden');
toggleMenuFlag(selection, 'hidden');
//Also mark all of it's submenus as hidden/visible
if ( menuHasFlag(selection,'hidden') ){
$('#' + selection.attr('submenu_id') + ' .ws_item').each(function(){
addMenuFlag(this, 'hidden');
});
} else {
$('#' + selection.attr('submenu_id') + ' .ws_item').each(function(){
removeMenuFlag(this, 'hidden');
});
}
});
//Delete menu
$('#ws_delete_menu').click(function () {
//Get the selected menu
var selection = $('#ws_menu_box .ws_active');
if (!selection.length) return;
if (confirm('Are you sure you want to delete this menu?')){
//Delete the submenu first
$('#' + selection.attr('submenu_id')).remove();
//Delete the menu
selection.remove();
}
});
//Copy menu
$('#ws_copy_menu').click(function () {
//Get the selected menu
var selection = $('#ws_menu_box .ws_active');
if (!selection.length) return;
//Store a copy in clipboard
menu_in_clipboard = selection.clone(true); //just like that
menu_in_clipboard.removeClass('ws_active');
submenu_in_clipboard = $('#'+selection.attr('submenu_id')).clone(true);
});
//Cut menu
$('#ws_cut_menu').click(function () {
//Get the selected menu
var selection = $('#ws_menu_box .ws_active');
if (!selection.length) return;
//Store a copy of both menu and it's submenu in clipboard
menu_in_clipboard = selection.removeClass('ws_active').clone(true);
menu_in_clipboard.removeClass('ws_active');
submenu_in_clipboard = $('#'+selection.attr('submenu_id')).clone(true);
//Remove the original menu and submenu
selection.remove();
$('#'+selection.attr('submenu_id')).remove;
});
//Paste menu
$('#ws_paste_menu').click(function () {
//Check if anything has been copied/cut
if (!menu_in_clipboard) return;
//Get the selected menu
var selection = $('#ws_menu_box .ws_active');
ws_paste_count++;
//Clone new objects from the virtual clipboard
var new_menu = menu_in_clipboard.clone(true);
var new_submenu = submenu_in_clipboard.clone(true);
//Close submenu editboxes
new_submenu.find('.ws_editbox').hide();
//The cloned menu must have a unique file name, unless it's a separator
if (!new_menu.hasClass('ws_menu_separator')) {
new_menu.find('.ws_edit_field[field_name="file"] input').val('custom_menu_'+ws_paste_count);
}
//The cloned submenu needs a unique ID (could be improved)
new_submenu.attr('id', 'ws-pasted-obj-'+ws_paste_count);
new_menu.attr('submenu_id', 'ws-pasted-obj-'+ws_paste_count);
//Make the new submenu sortable
new_submenu.sortable({
items: '> .ws_container',
cursor: 'move',
dropOnEmpty: true,
});
if (selection.length > 0) {
//If a menu is selected add the pasted item after it
selection.after(new_menu);
} else {
//Otherwise add the pasted item at the end
$('#ws_menu_box').append(new_menu);
};
//Insert the submenu in the box, too
$('#ws_submenu_box').append(new_submenu);
new_menu.show();
new_submenu.hide();
});
//New menu
$('#ws_new_menu').click(function () {
ws_paste_count++;
//This is a hack.
//Clone another menu to use as a template
var menu = $('#ws_menu_box .ws_menu:first').clone(true);
//Also clone a submenu
var submenu = $('#' + menu.attr('submenu_id')).clone(true);
//Assign a new ID
submenu.attr('id', 'ws-new-submenu-'+ws_paste_count);
menu.attr('submenu_id', 'ws-new-submenu-'+ws_paste_count);
//Remove all items from the submenu
submenu.empty();
//Make the submenu sortable
submenu.sortable({
items: '> .ws_container',
cursor: 'move',
dropOnEmpty: true,
});
//Clean up the menu's flags & classes
menu.attr('class','ws_container ws_menu');
clearMenuFlags(menu);
addMenuFlag(menu, 'custom_item');
//Check the "Custom" checkbox
menu.find('.ws_custom_toggle').attr('checked', 'checked');
var temp_id = 'custom_menu_'+ws_paste_count;
//Assign a stub title
menu.find('.ws_item_title').text('Custom Menu '+ws_paste_count);
//All fields start out set to defaults
menu.find('input').attr('default','').addClass('ws_input_default');
//Set all fields
menu.find('.ws_edit_field[field_name="page_title"] input').val('').attr('default','');
menu.find('.ws_edit_field[field_name="menu_title"] input').val('Custom Menu '+ws_paste_count).attr('default','Custom Menu '+ws_paste_count);
menu.find('.ws_edit_field[field_name="access_level"] input').val('read').attr('default','read');
menu.find('.ws_edit_field[field_name="file"] input').val(temp_id).attr('default',temp_id);
menu.find('.ws_edit_field[field_name="css_class"] input').val('menu-top').attr('default','menu-top');
menu.find('.ws_edit_field[field_name="icon_url"] input').val('images/generic.png').attr('default','images/generic.png');
menu.find('.ws_edit_field[field_name="hookname"] input').val(temp_id).attr('default',temp_id);
//The menus's editbox is always open
menu.find('.ws_editbox').show();
//Make sure the edit link is in the right state, too
menu.find('.ws_edit_link').addClass('ws_edit_link_expanded');
//Finally, insert the menu into the box
$('#ws_menu_box').append(menu);
//And insert the submenu
$('#ws_submenu_box').append(submenu);
});
//===== Item toolbar buttons =======
//Show/Hide item
$('#ws_hide_item').click(function () {
//Get the selected item
var selection = $('#ws_submenu_box .ws_submenu:visible .ws_active');
if (!selection.length) return;
//Mark the item as hidden
toggleMenuFlag(selection, 'hidden');
});
//Delete menu
$('#ws_delete_item').click(function () {
//Get the selected menu
var selection = $('#ws_submenu_box .ws_submenu:visible .ws_active');
if (!selection.length) return;
if (confirm('Are you sure you want to delete this menu item?')){
//Delete the item
selection.remove();
}
});
//Copy item
$('#ws_copy_item').click(function () {
//Get the selected item
var selection = $('#ws_submenu_box .ws_submenu:visible .ws_active');
if (!selection.length) return;
//Store a copy in clipboard
item_in_clipboard = selection.clone(true); //just like that
item_in_clipboard.removeClass('ws_active');
});
//Cut item
$('#ws_cut_item').click(function () {
//Get the selected item
var selection = $('#ws_submenu_box .ws_submenu:visible .ws_active');
if (!selection.length) return;
//Store a the item in clipboard
item_in_clipboard = selection.clone(true);
item_in_clipboard.removeClass('ws_active');
//Remove the original item
selection.remove();
});
//Paste item
$('#ws_paste_item').click(function () {
//Check if anything has been copied/cut
if (!item_in_clipboard) return;
//Get the selected menu
var selection = $('#ws_submenu_box .ws_submenu:visible .ws_active');
ws_paste_count++;
//Clone a new object from the virtual clipboard
var new_item = item_in_clipboard.clone(true);
//The item's editbox is always closed
new_item.find('.ws_editbox').hide();
if (selection.length > 0) {
//If an item is selected add the pasted item after it
selection.after(new_item);
} else {
//Otherwise add the pasted item at the end
$('#ws_submenu_box .ws_submenu:visible').append(new_item);
};
new_item.show();
});
//New item
$('#ws_new_item').click(function () {
if ($('.ws_submenu:visible').length<1) return; //abort if no submenu visible
ws_paste_count++;
//Clone another item to use as a template (hack)
var menu = $('#ws_submenu_box .ws_item:first').clone(true);
//Cleanup the items's flags & classes
menu.attr('class','ws_container ws_item');
clearMenuFlags(menu);
addMenuFlag(menu, 'custom_item');
//Check the "Custom" checkbox
menu.find('.ws_custom_toggle').attr('checked', 'checked');
var temp_id = 'custom_item_'+ws_paste_count;
//Assign a stub title
menu.find('.ws_item_title').text('Custom Item '+ws_paste_count);
//All fields start out set to defaults
menu.find('input').attr('default','').addClass('ws_input_default');
//Set all fields
menu.find('.ws_edit_field[field_name="page_title"] input').val('').attr('default','');
menu.find('.ws_edit_field[field_name="menu_title"] input').val('Custom Item '+ws_paste_count).attr('default','Custom Item '+ws_paste_count);
menu.find('.ws_edit_field[field_name="access_level"] input').val('read').attr('default','read');
menu.find('.ws_edit_field[field_name="file"] input').val(temp_id).attr('default',temp_id);
//The items's editbox is always open
menu.find('.ws_editbox').show();
//Make sure the edit link is in the right state, too
menu.find('.ws_edit_link').addClass('ws_edit_link_expanded');
//Finally, insert the item into the box
$('.ws_submenu:visible').append(menu);
});
//==============================================
// Main buttons
//==============================================
//Save Changes - encode the current menu as JSON and save
$('#ws_save_menu').click(function () {
var data = encodeMenuAsJSON();
$('#ws_data').val(data);
$('#ws_main_form').submit();
});
//Load default menu - load the default WordPress menu
$('#ws_load_menu').click(function () {
if (confirm('Are you sure you want to load the default WordPress menu into the editor?')){
outputWpMenu(defaultMenu);
}
});
//Reset menu - re-load the custom menu = discards any changes made by user
$('#ws_reset_menu').click(function () {
if (confirm('Are you sure you want to reset the custom menu? Any unsaved changes will be lost!')){
outputWpMenu(customMenu);
}
});
});
})(jQuery);