//(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 = '
'+ '
'+ ' '+ '
'+ ''+ ((menu.menu_title!=null)?menu.menu_title:menu.defaults.menu_title)+ ' '+ '
'+ ''+ '
'; 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 = $( '
'+ '
'+ ' '+ '
'+ ''+ ((entry.menu_title!=null)?entry.menu_title:entry.defaults.menu_title)+ ' '+ '
'+ ''+ '
' ).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);