1 var wpNavMenu;(function(b){var a=wpNavMenu={options:{menuItemDepthPerLevel:30,globalMaxDepth:11},menuList:undefined,targetList:undefined,menusChanged:false,isRTL:!!("undefined"!=typeof isRtl&&isRtl),negateIfRTL:("undefined"!=typeof isRtl&&isRtl)?-1:1,init:function(){a.menuList=b("#menu-to-edit");a.targetList=a.menuList;this.jQueryExtensions();this.attachMenuEditListeners();this.setupInputWithDefaultTitle();this.attachQuickSearchListeners();this.attachThemeLocationsListeners();this.attachTabsPanelListeners();this.attachUnsavedChangesListener();if(a.menuList.length){this.initSortables()}this.initToggles();this.initTabManager()},jQueryExtensions:function(){b.fn.extend({menuItemDepth:function(){var c=a.isRTL?this.eq(0).css("margin-right"):this.eq(0).css("margin-left");return a.pxToDepth(c&&-1!=c.indexOf("px")?c.slice(0,-2):0)},updateDepthClass:function(d,c){return this.each(function(){var e=b(this);c=c||e.menuItemDepth();b(this).removeClass("menu-item-depth-"+c).addClass("menu-item-depth-"+d)})},shiftDepthClass:function(c){return this.each(function(){var d=b(this),e=d.menuItemDepth();b(this).removeClass("menu-item-depth-"+e).addClass("menu-item-depth-"+(e+c))})},childMenuItems:function(){var c=b();this.each(function(){var d=b(this),f=d.menuItemDepth(),e=d.next();while(e.length&&e.menuItemDepth()>f){c=c.add(e);e=e.next()}});return c},updateParentMenuItemDBId:function(){return this.each(function(){var e=b(this),c=e.find(".menu-item-data-parent-id"),f=e.menuItemDepth(),d=e.prev();if(f==0){c.val(0)}else{while(!d[0]||!d[0].className||-1==d[0].className.indexOf("menu-item")||(d.menuItemDepth()!=f-1)){d=d.prev()}c.val(d.find(".menu-item-data-db-id").val())}})},hideAdvancedMenuItemFields:function(){return this.each(function(){var c=b(this);b(".hide-column-tog").not(":checked").each(function(){c.find(".field-"+b(this).val()).addClass("hidden-field")})})},addSelectedToMenu:function(c){if(0==b("#menu-to-edit").length){return false}return this.each(function(){var e=b(this),d={},g=e.find(".tabs-panel-active .categorychecklist li input:checked"),f=new RegExp("menu-item\\[([^\\]]*)");c=c||a.addMenuItemToBottom;if(!g.length){return false}e.find("img.waiting").show();b(g).each(function(){var i=b(this),h=f.exec(i.attr("name")),j="undefined"==typeof h[1]?0:parseInt(h[1],10);if(this.className&&-1!=this.className.indexOf("add-to-top")){c=a.addMenuItemToTop}d[j]=i.closest("li").getItemData("add-menu-item",j)});a.addItemToMenu(d,c,function(){g.removeAttr("checked");e.find("img.waiting").hide()})})},getItemData:function(f,g){f=f||"menu-item";var d={},e,c=["menu-item-db-id","menu-item-object-id","menu-item-object","menu-item-parent-id","menu-item-position","menu-item-type","menu-item-title","menu-item-url","menu-item-description","menu-item-attr-title","menu-item-target","menu-item-classes","menu-item-xfn"];if(!g&&f=="menu-item"){g=this.find(".menu-item-data-db-id").val()}if(!g){return d}this.find("input").each(function(){var h;e=c.length;while(e--){if(f=="menu-item"){h=c[e]+"["+g+"]"}else{if(f=="add-menu-item"){h="menu-item["+g+"]["+c[e]+"]"}}if(this.name&&h==this.name){d[c[e]]=this.value}}});return d},setItemData:function(c,d,e){d=d||"menu-item";if(!e&&d=="menu-item"){e=b(".menu-item-data-db-id",this).val()}if(!e){return this}this.find("input").each(function(){var f=b(this),g;b.each(c,function(h,i){if(d=="menu-item"){g=h+"["+e+"]"}else{if(d=="add-menu-item"){g="menu-item["+e+"]["+h+"]"}}if(g==f.attr("name")){f.val(i)}})});return this}})},initToggles:function(){postboxes.add_postbox_toggles("nav-menus");columns.useCheckboxesForHidden();columns.checked=function(c){b(".field-"+c).removeClass("hidden-field")};columns.unchecked=function(c){b(".field-"+c).addClass("hidden-field")};a.menuList.hideAdvancedMenuItemFields()},initSortables:function(){var p=0,e,t,d,l,o,f,c,i,s,m=a.menuList.offset().left,h=b("body"),q,n=r();m+=a.isRTL?a.menuList.width():0;a.menuList.sortable({handle:".menu-item-handle",placeholder:"sortable-placeholder",start:function(A,z){var u,x,w,v,y;if(a.isRTL){z.item[0].style.right="auto"}s=z.item.children(".menu-item-transport");e=z.item.menuItemDepth();j(z,e);w=(z.item.next()[0]==z.placeholder[0])?z.item.next():z.item;v=w.childMenuItems();s.append(v);u=s.outerHeight();u+=(u>0)?(z.placeholder.css("margin-top").slice(0,-2)*1):0;u+=z.helper.outerHeight();i=u;u-=2;z.placeholder.height(u);q=e;v.each(function(){var B=b(this).menuItemDepth();q=(B>q)?B:q});x=z.helper.find(".menu-item-handle").outerWidth();x+=a.depthToPx(q-e);x-=2;z.placeholder.width(x);y=z.placeholder.next();y.css("margin-top",i+"px");z.placeholder.detach();b(this).sortable("refresh");z.item.after(z.placeholder);y.css("margin-top",0);k(z)},stop:function(x,w){var v,u=p-e;v=s.children().insertAfter(w.item);if(u!=0){w.item.updateDepthClass(p);v.shiftDepthClass(u);g(u)}a.registerChange();w.item.updateParentMenuItemDBId();w.item[0].style.top=0;if(a.isRTL){w.item[0].style.left="auto";w.item[0].style.right=0}a.refreshMenuTabs(true)},change:function(v,u){if(!u.placeholder.parent().hasClass("menu")){(l.length)?l.after(u.placeholder):a.menuList.prepend(u.placeholder)}k(u)},sort:function(w,v){var y=v.helper.offset(),u=a.isRTL?y.left+v.helper.width():y.left,x=a.negateIfRTL*a.pxToDepth(u-m);if(x>d||y.top<f){x=d}else{if(x<t){x=t}}if(x!=p){j(v,x)}if(c&&y.top+i>c){o.after(v.placeholder);k(v);b(this).sortable("refreshPositions")}}});function k(u){var v;l=u.placeholder.prev();o=u.placeholder.next();if(l[0]==u.item[0]){l=l.prev()}if(o[0]==u.item[0]){o=o.next()}f=(l.length)?l.offset().top+l.height():0;c=(o.length)?o.offset().top+o.height()/3:0;t=(o.length)?o.menuItemDepth():0;if(l.length){d=((v=l.menuItemDepth()+1)>a.options.globalMaxDepth)?a.options.globalMaxDepth:v}else{d=0}}function j(u,v){u.placeholder.updateDepthClass(v,p);p=v}function r(){if(!h[0].className){return 0}var u=h[0].className.match(/menu-max-depth-(\d+)/);return u&&u[1]?parseInt(u[1]):0}function g(u){var v,w=n;if(u===0){return}else{if(u>0){v=q+u;if(v>n){w=v}}else{if(u<0&&q==n){while(!b(".menu-item-depth-"+w,a.menuList).length&&w>0){w--}}}}h.removeClass("menu-max-depth-"+n).addClass("menu-max-depth-"+w);n=w}},attachMenuEditListeners:function(){var c=this;b("#update-nav-menu").bind("click",function(d){if(d.target&&d.target.className){if(-1!=d.target.className.indexOf("item-edit")){return c.eventOnClickEditLink(d.target)}else{if(-1!=d.target.className.indexOf("menu-save")){return c.eventOnClickMenuSave(d.target)}else{if(-1!=d.target.className.indexOf("menu-delete")){return c.eventOnClickMenuDelete(d.target)}else{if(-1!=d.target.className.indexOf("item-delete")){return c.eventOnClickMenuItemDelete(d.target)}else{if(-1!=d.target.className.indexOf("item-cancel")){return c.eventOnClickCancelLink(d.target)}}}}}}});b('#add-custom-links input[type="text"]').keypress(function(d){if(d.keyCode===13){d.preventDefault();b("#submit-customlinkdiv").click()}})},setupInputWithDefaultTitle:function(){var c="input-with-default-title";b("."+c).each(function(){var f=b(this),e=f.attr("title"),d=f.val();f.data(c,e);if(""==d){f.val(e)}else{if(e==d){return}else{f.removeClass(c)}}}).focus(function(){var d=b(this);if(d.val()==d.data(c)){d.val("").removeClass(c)}}).blur(function(){var d=b(this);if(""==d.val()){d.addClass(c).val(d.data(c))}})},attachThemeLocationsListeners:function(){var d=b("#nav-menu-theme-locations"),c={};c.action="menu-locations-save";c["menu-settings-column-nonce"]=b("#menu-settings-column-nonce").val();d.find('input[type="submit"]').click(function(){d.find("select").each(function(){c[this.name]=b(this).val()});d.find(".waiting").show();b.post(ajaxurl,c,function(e){d.find(".waiting").hide()});return false})},attachQuickSearchListeners:function(){var c;b(".quick-search").keypress(function(f){var d=b(this);if(13==f.which){a.updateQuickSearchResults(d);return false}if(c){clearTimeout(c)}c=setTimeout(function(){a.updateQuickSearchResults(d)},400)}).attr("autocomplete","off")},updateQuickSearchResults:function(d){var c,g,e=2,f=d.val();if(f.length<e){return}c=d.parents(".tabs-panel");g={action:"menu-quick-search","response-format":"markup",menu:b("#menu").val(),"menu-settings-column-nonce":b("#menu-settings-column-nonce").val(),q:f,type:d.attr("name")};b("img.waiting",c).show();b.post(ajaxurl,g,function(h){a.processQuickSearchQueryResponse(h,g,c)})},addCustomLink:function(c){var e=b("#custom-menu-item-url").val(),d=b("#custom-menu-item-name").val();c=c||a.addMenuItemToBottom;if(""==e||"http://"==e){return false}b(".customlinkdiv img.waiting").show();this.addLinkToMenu(e,d,c,function(){b(".customlinkdiv img.waiting").hide();b("#custom-menu-item-name").val("").blur();b("#custom-menu-item-url").val("http://")})},addLinkToMenu:function(e,d,c,f){c=c||a.addMenuItemToBottom;f=f||function(){};a.addItemToMenu({"-1":{"menu-item-type":"custom","menu-item-url":e,"menu-item-title":d}},c,f)},addItemToMenu:function(e,c,g){var f=b("#menu").val(),d=b("#menu-settings-column-nonce").val();c=c||function(){};g=g||function(){};params={action:"add-menu-item",menu:f,"menu-settings-column-nonce":d,"menu-item":e};b.post(ajaxurl,params,function(h){var i=b("#menu-instructions");c(h,params);if(!i.hasClass("menu-instructions-inactive")&&i.siblings().length){i.addClass("menu-instructions-inactive")}g()})},addMenuItemToBottom:function(c,d){b(c).hideAdvancedMenuItemFields().appendTo(a.targetList)},addMenuItemToTop:function(c,d){b(c).hideAdvancedMenuItemFields().prependTo(a.targetList)},attachUnsavedChangesListener:function(){b("#menu-management input, #menu-management select, #menu-management, #menu-management textarea").change(function(){a.registerChange()});if(0!=b("#menu-to-edit").length){window.onbeforeunload=function(){if(a.menusChanged){return navMenuL10n.saveAlert}}}else{b("#menu-settings-column").find("input,select").prop("disabled",true).end().find("a").attr("href","#").unbind("click")}},registerChange:function(){a.menusChanged=true},attachTabsPanelListeners:function(){b("#menu-settings-column").bind("click",function(h){var f,d,i,c,g=b(h.target);if(g.hasClass("nav-tab-link")){d=/#(.*)$/.exec(h.target.href);if(d&&d[1]){d=d[1]}else{return false}i=g.parents(".inside").first();b("input",i).removeAttr("checked");b(".tabs-panel-active",i).removeClass("tabs-panel-active").addClass("tabs-panel-inactive");b("#"+d,i).removeClass("tabs-panel-inactive").addClass("tabs-panel-active");b(".tabs",i).removeClass("tabs");g.parent().addClass("tabs");b(".quick-search",i).focus();return false}else{if(g.hasClass("select-all")){f=/#(.*)$/.exec(h.target.href);if(f&&f[1]){c=b("#"+f[1]+" .tabs-panel-active .menu-item-title input");if(c.length===c.filter(":checked").length){c.removeAttr("checked")}else{c.prop("checked",true)}return false}}else{if(g.hasClass("submit-add-to-menu")){a.registerChange();if(h.target.id&&"submit-customlinkdiv"==h.target.id){a.addCustomLink(a.addMenuItemToBottom)}else{if(h.target.id&&-1!=h.target.id.indexOf("submit-")){b("#"+h.target.id.replace(/submit-/,"")).addSelectedToMenu(a.addMenuItemToBottom)}}return false}else{if(g.hasClass("page-numbers")){b.post(ajaxurl,h.target.href.replace(/.*\?/,"").replace(/action=([^&]*)/,"")+"&action=menu-get-metabox",function(m){if(-1==m.indexOf("replace-id")){return}var l=b.parseJSON(m),e=document.getElementById(l["replace-id"]),k=document.createElement("div"),j=document.createElement("div");if(!l.markup||!e){return}j.innerHTML=l.markup?l.markup:"";e.parentNode.insertBefore(k,e);k.parentNode.removeChild(e);k.parentNode.insertBefore(j,k);k.parentNode.removeChild(k)});return false}}}}})},initTabManager:function(){var h=b(".nav-tabs-wrapper"),j=h.children(".nav-tabs"),g=j.children(".nav-tab-active"),m=j.children(".nav-tab"),e=0,o,f,l,d,k,i={},c=a.isRTL?"margin-right":"margin-left",p=a.isRTL?"margin-left":"margin-right",n=2;a.refreshMenuTabs=function(q){var t=h.width(),s=0,r={};f=h.offset().left;o=f+t;if(!q){g.makeTabVisible()}if(m.last().isTabVisible()){s=h.width()-e;s=s>0?0:s;r[c]=s+"px";j.animate(r,100,"linear")}if(t>e){l.add(d).hide()}else{l.add(d).show()}};b.fn.extend({makeTabVisible:function(){var u=this.eq(0),v,s,r={},q=0;if(!u.length){return this}v=u.offset().left;s=v+u.outerWidth();if(s>o){q=o-s}else{if(v<f){q=f-v}}if(!q){return this}r[c]="+="+a.negateIfRTL*q+"px";j.animate(r,Math.abs(q)*n,"linear");return this},isTabVisible:function(){var r=this.eq(0),s=r.offset().left,q=s+r.outerWidth();return(q<=o&&s>=f)?true:false}});m.each(function(){e+=b(this).outerWidth(true)});i.padding=0;i[p]=(-1*e)+"px";j.css(i);l=b('<div class="nav-tabs-arrow nav-tabs-arrow-left"><a>«</a></div>');d=b('<div class="nav-tabs-arrow nav-tabs-arrow-right"><a>»</a></div>');h.wrap('<div class="nav-tabs-nav"/>').parent().prepend(l).append(d);a.refreshMenuTabs();b(window).resize(function(){if(k){clearTimeout(k)}k=setTimeout(a.refreshMenuTabs,200)});b.each([{arrow:l,next:"next",last:"first",operator:"+="},{arrow:d,next:"prev",last:"last",operator:"-="}],function(){var q=this;this.arrow.mousedown(function(){var t=Math.abs(parseInt(j.css(c))),r=t,s={};if("-="==q.operator){r=Math.abs(e-h.width())-t}if(!r){return}s[c]=q.operator+r+"px";j.animate(s,r*n,"linear")}).mouseup(function(){var s,r;j.stop(true);s=m[q.last]();while((r=s[q.next]())&&r.length&&!r.isTabVisible()){s=r}s.makeTabVisible()})})},eventOnClickEditLink:function(d){var c,e,f=/#(.*)$/.exec(d.href);if(f&&f[1]){c=b("#"+f[1]);e=c.parent();if(0!=e.length){if(e.hasClass("menu-item-edit-inactive")){if(!c.data("menu-item-data")){c.data("menu-item-data",c.getItemData())}c.slideDown("fast");e.removeClass("menu-item-edit-inactive").addClass("menu-item-edit-active")}else{c.slideUp("fast");e.removeClass("menu-item-edit-active").addClass("menu-item-edit-inactive")}return false}}},eventOnClickCancelLink:function(d){var c=b(d).closest(".menu-item-settings");c.setItemData(c.data("menu-item-data"));return false},eventOnClickMenuSave:function(e){var f="",c=b("#menu-name"),d=c.val();if(!d||d==c.attr("title")||!d.replace(/\s+/,"")){c.parent().addClass("form-invalid");return false}b("#nav-menu-theme-locations select").each(function(){f+='<input type="hidden" name="'+this.name+'" value="'+b(this).val()+'" />'});b("#update-nav-menu").append(f);a.menuList.find(".menu-item-data-position").val(function(g){return g+1});window.onbeforeunload=null;return true},eventOnClickMenuDelete:function(c){if(confirm(navMenuL10n.warnDeleteMenu)){window.onbeforeunload=null;return true}return false},eventOnClickMenuItemDelete:function(c){var d=parseInt(c.id.replace("delete-",""),10);a.removeMenuItem(b("#menu-item-"+d));a.registerChange();return false},processQuickSearchQueryResponse:function(g,k,c){var e,i,f={},d=document.getElementById("nav-menu-meta"),j=new RegExp("menu-item\\[([^\\]]*)","g"),h=b("<div>").html(g).find("li"),l;if(!h.length){b(".categorychecklist",c).html("<li><p>"+navMenuL10n.noResultsFound+"</p></li>");b("img.waiting",c).hide();return}h.each(function(){l=b(this);e=j.exec(l.html());if(e&&e[1]){i=e[1];while(d.elements["menu-item["+i+"][menu-item-type]"]||f[i]){i--}f[i]=true;if(i!=e[1]){l.html(l.html().replace(new RegExp("menu-item\\["+e[1]+"\\]","g"),"menu-item["+i+"]"))}}});b(".categorychecklist",c).html(h);b("img.waiting",c).hide()},removeMenuItem:function(d){var c=d.childMenuItems();d.addClass("deleting").animate({opacity:0,height:0},350,function(){var e=b("#menu-instructions");d.remove();c.shiftDepthClass(-1).updateParentMenuItemDBId();if(!e.siblings().length){e.removeClass("menu-instructions-inactive")}})},depthToPx:function(c){return c*a.options.menuItemDepthPerLevel},pxToDepth:function(c){return Math.floor(c/a.options.menuItemDepthPerLevel)}};b(document).ready(function(){wpNavMenu.init()})})(jQuery); |
1 /** |
|
2 * WordPress Administration Navigation Menu |
|
3 * Interface JS functions |
|
4 * |
|
5 * @version 2.0.0 |
|
6 * |
|
7 * @package WordPress |
|
8 * @subpackage Administration |
|
9 */ |
|
10 |
|
11 var wpNavMenu; |
|
12 |
|
13 (function($) { |
|
14 |
|
15 var api = wpNavMenu = { |
|
16 |
|
17 options : { |
|
18 menuItemDepthPerLevel : 30, // Do not use directly. Use depthToPx and pxToDepth instead. |
|
19 globalMaxDepth : 11 |
|
20 }, |
|
21 |
|
22 menuList : undefined, // Set in init. |
|
23 targetList : undefined, // Set in init. |
|
24 menusChanged : false, |
|
25 isRTL: !! ( 'undefined' != typeof isRtl && isRtl ), |
|
26 negateIfRTL: ( 'undefined' != typeof isRtl && isRtl ) ? -1 : 1, |
|
27 |
|
28 // Functions that run on init. |
|
29 init : function() { |
|
30 api.menuList = $('#menu-to-edit'); |
|
31 api.targetList = api.menuList; |
|
32 |
|
33 this.jQueryExtensions(); |
|
34 |
|
35 this.attachMenuEditListeners(); |
|
36 |
|
37 this.setupInputWithDefaultTitle(); |
|
38 this.attachQuickSearchListeners(); |
|
39 this.attachThemeLocationsListeners(); |
|
40 |
|
41 this.attachTabsPanelListeners(); |
|
42 |
|
43 this.attachUnsavedChangesListener(); |
|
44 |
|
45 if( api.menuList.length ) // If no menu, we're in the + tab. |
|
46 this.initSortables(); |
|
47 |
|
48 this.initToggles(); |
|
49 |
|
50 this.initTabManager(); |
|
51 }, |
|
52 |
|
53 jQueryExtensions : function() { |
|
54 // jQuery extensions |
|
55 $.fn.extend({ |
|
56 menuItemDepth : function() { |
|
57 var margin = api.isRTL ? this.eq(0).css('margin-right') : this.eq(0).css('margin-left'); |
|
58 return api.pxToDepth( margin && -1 != margin.indexOf('px') ? margin.slice(0, -2) : 0 ); |
|
59 }, |
|
60 updateDepthClass : function(current, prev) { |
|
61 return this.each(function(){ |
|
62 var t = $(this); |
|
63 prev = prev || t.menuItemDepth(); |
|
64 $(this).removeClass('menu-item-depth-'+ prev ) |
|
65 .addClass('menu-item-depth-'+ current ); |
|
66 }); |
|
67 }, |
|
68 shiftDepthClass : function(change) { |
|
69 return this.each(function(){ |
|
70 var t = $(this), |
|
71 depth = t.menuItemDepth(); |
|
72 $(this).removeClass('menu-item-depth-'+ depth ) |
|
73 .addClass('menu-item-depth-'+ (depth + change) ); |
|
74 }); |
|
75 }, |
|
76 childMenuItems : function() { |
|
77 var result = $(); |
|
78 this.each(function(){ |
|
79 var t = $(this), depth = t.menuItemDepth(), next = t.next(); |
|
80 while( next.length && next.menuItemDepth() > depth ) { |
|
81 result = result.add( next ); |
|
82 next = next.next(); |
|
83 } |
|
84 }); |
|
85 return result; |
|
86 }, |
|
87 updateParentMenuItemDBId : function() { |
|
88 return this.each(function(){ |
|
89 var item = $(this), |
|
90 input = item.find('.menu-item-data-parent-id'), |
|
91 depth = item.menuItemDepth(), |
|
92 parent = item.prev(); |
|
93 |
|
94 if( depth == 0 ) { // Item is on the top level, has no parent |
|
95 input.val(0); |
|
96 } else { // Find the parent item, and retrieve its object id. |
|
97 while( ! parent[0] || ! parent[0].className || -1 == parent[0].className.indexOf('menu-item') || ( parent.menuItemDepth() != depth - 1 ) ) |
|
98 parent = parent.prev(); |
|
99 input.val( parent.find('.menu-item-data-db-id').val() ); |
|
100 } |
|
101 }); |
|
102 }, |
|
103 hideAdvancedMenuItemFields : function() { |
|
104 return this.each(function(){ |
|
105 var that = $(this); |
|
106 $('.hide-column-tog').not(':checked').each(function(){ |
|
107 that.find('.field-' + $(this).val() ).addClass('hidden-field'); |
|
108 }); |
|
109 }); |
|
110 }, |
|
111 /** |
|
112 * Adds selected menu items to the menu. |
|
113 * |
|
114 * @param jQuery metabox The metabox jQuery object. |
|
115 */ |
|
116 addSelectedToMenu : function(processMethod) { |
|
117 if ( 0 == $('#menu-to-edit').length ) { |
|
118 return false; |
|
119 } |
|
120 |
|
121 return this.each(function() { |
|
122 var t = $(this), menuItems = {}, |
|
123 checkboxes = t.find('.tabs-panel-active .categorychecklist li input:checked'), |
|
124 re = new RegExp('menu-item\\[(\[^\\]\]*)'); |
|
125 |
|
126 processMethod = processMethod || api.addMenuItemToBottom; |
|
127 |
|
128 // If no items are checked, bail. |
|
129 if ( !checkboxes.length ) |
|
130 return false; |
|
131 |
|
132 // Show the ajax spinner |
|
133 t.find('.spinner').show(); |
|
134 |
|
135 // Retrieve menu item data |
|
136 $(checkboxes).each(function(){ |
|
137 var t = $(this), |
|
138 listItemDBIDMatch = re.exec( t.attr('name') ), |
|
139 listItemDBID = 'undefined' == typeof listItemDBIDMatch[1] ? 0 : parseInt(listItemDBIDMatch[1], 10); |
|
140 if ( this.className && -1 != this.className.indexOf('add-to-top') ) |
|
141 processMethod = api.addMenuItemToTop; |
|
142 menuItems[listItemDBID] = t.closest('li').getItemData( 'add-menu-item', listItemDBID ); |
|
143 }); |
|
144 |
|
145 // Add the items |
|
146 api.addItemToMenu(menuItems, processMethod, function(){ |
|
147 // Deselect the items and hide the ajax spinner |
|
148 checkboxes.removeAttr('checked'); |
|
149 t.find('.spinner').hide(); |
|
150 }); |
|
151 }); |
|
152 }, |
|
153 getItemData : function( itemType, id ) { |
|
154 itemType = itemType || 'menu-item'; |
|
155 |
|
156 var itemData = {}, i, |
|
157 fields = [ |
|
158 'menu-item-db-id', |
|
159 'menu-item-object-id', |
|
160 'menu-item-object', |
|
161 'menu-item-parent-id', |
|
162 'menu-item-position', |
|
163 'menu-item-type', |
|
164 'menu-item-title', |
|
165 'menu-item-url', |
|
166 'menu-item-description', |
|
167 'menu-item-attr-title', |
|
168 'menu-item-target', |
|
169 'menu-item-classes', |
|
170 'menu-item-xfn' |
|
171 ]; |
|
172 |
|
173 if( !id && itemType == 'menu-item' ) { |
|
174 id = this.find('.menu-item-data-db-id').val(); |
|
175 } |
|
176 |
|
177 if( !id ) return itemData; |
|
178 |
|
179 this.find('input').each(function() { |
|
180 var field; |
|
181 i = fields.length; |
|
182 while ( i-- ) { |
|
183 if( itemType == 'menu-item' ) |
|
184 field = fields[i] + '[' + id + ']'; |
|
185 else if( itemType == 'add-menu-item' ) |
|
186 field = 'menu-item[' + id + '][' + fields[i] + ']'; |
|
187 |
|
188 if ( |
|
189 this.name && |
|
190 field == this.name |
|
191 ) { |
|
192 itemData[fields[i]] = this.value; |
|
193 } |
|
194 } |
|
195 }); |
|
196 |
|
197 return itemData; |
|
198 }, |
|
199 setItemData : function( itemData, itemType, id ) { // Can take a type, such as 'menu-item', or an id. |
|
200 itemType = itemType || 'menu-item'; |
|
201 |
|
202 if( !id && itemType == 'menu-item' ) { |
|
203 id = $('.menu-item-data-db-id', this).val(); |
|
204 } |
|
205 |
|
206 if( !id ) return this; |
|
207 |
|
208 this.find('input').each(function() { |
|
209 var t = $(this), field; |
|
210 $.each( itemData, function( attr, val ) { |
|
211 if( itemType == 'menu-item' ) |
|
212 field = attr + '[' + id + ']'; |
|
213 else if( itemType == 'add-menu-item' ) |
|
214 field = 'menu-item[' + id + '][' + attr + ']'; |
|
215 |
|
216 if ( field == t.attr('name') ) { |
|
217 t.val( val ); |
|
218 } |
|
219 }); |
|
220 }); |
|
221 return this; |
|
222 } |
|
223 }); |
|
224 }, |
|
225 |
|
226 initToggles : function() { |
|
227 // init postboxes |
|
228 postboxes.add_postbox_toggles('nav-menus'); |
|
229 |
|
230 // adjust columns functions for menus UI |
|
231 columns.useCheckboxesForHidden(); |
|
232 columns.checked = function(field) { |
|
233 $('.field-' + field).removeClass('hidden-field'); |
|
234 } |
|
235 columns.unchecked = function(field) { |
|
236 $('.field-' + field).addClass('hidden-field'); |
|
237 } |
|
238 // hide fields |
|
239 api.menuList.hideAdvancedMenuItemFields(); |
|
240 }, |
|
241 |
|
242 initSortables : function() { |
|
243 var currentDepth = 0, originalDepth, minDepth, maxDepth, |
|
244 prev, next, prevBottom, nextThreshold, helperHeight, transport, |
|
245 menuEdge = api.menuList.offset().left, |
|
246 body = $('body'), maxChildDepth, |
|
247 menuMaxDepth = initialMenuMaxDepth(); |
|
248 |
|
249 // Use the right edge if RTL. |
|
250 menuEdge += api.isRTL ? api.menuList.width() : 0; |
|
251 |
|
252 api.menuList.sortable({ |
|
253 handle: '.menu-item-handle', |
|
254 placeholder: 'sortable-placeholder', |
|
255 start: function(e, ui) { |
|
256 var height, width, parent, children, tempHolder; |
|
257 |
|
258 // handle placement for rtl orientation |
|
259 if ( api.isRTL ) |
|
260 ui.item[0].style.right = 'auto'; |
|
261 |
|
262 transport = ui.item.children('.menu-item-transport'); |
|
263 |
|
264 // Set depths. currentDepth must be set before children are located. |
|
265 originalDepth = ui.item.menuItemDepth(); |
|
266 updateCurrentDepth(ui, originalDepth); |
|
267 |
|
268 // Attach child elements to parent |
|
269 // Skip the placeholder |
|
270 parent = ( ui.item.next()[0] == ui.placeholder[0] ) ? ui.item.next() : ui.item; |
|
271 children = parent.childMenuItems(); |
|
272 transport.append( children ); |
|
273 |
|
274 // Update the height of the placeholder to match the moving item. |
|
275 height = transport.outerHeight(); |
|
276 // If there are children, account for distance between top of children and parent |
|
277 height += ( height > 0 ) ? (ui.placeholder.css('margin-top').slice(0, -2) * 1) : 0; |
|
278 height += ui.helper.outerHeight(); |
|
279 helperHeight = height; |
|
280 height -= 2; // Subtract 2 for borders |
|
281 ui.placeholder.height(height); |
|
282 |
|
283 // Update the width of the placeholder to match the moving item. |
|
284 maxChildDepth = originalDepth; |
|
285 children.each(function(){ |
|
286 var depth = $(this).menuItemDepth(); |
|
287 maxChildDepth = (depth > maxChildDepth) ? depth : maxChildDepth; |
|
288 }); |
|
289 width = ui.helper.find('.menu-item-handle').outerWidth(); // Get original width |
|
290 width += api.depthToPx(maxChildDepth - originalDepth); // Account for children |
|
291 width -= 2; // Subtract 2 for borders |
|
292 ui.placeholder.width(width); |
|
293 |
|
294 // Update the list of menu items. |
|
295 tempHolder = ui.placeholder.next(); |
|
296 tempHolder.css( 'margin-top', helperHeight + 'px' ); // Set the margin to absorb the placeholder |
|
297 ui.placeholder.detach(); // detach or jQuery UI will think the placeholder is a menu item |
|
298 $(this).sortable( "refresh" ); // The children aren't sortable. We should let jQ UI know. |
|
299 ui.item.after( ui.placeholder ); // reattach the placeholder. |
|
300 tempHolder.css('margin-top', 0); // reset the margin |
|
301 |
|
302 // Now that the element is complete, we can update... |
|
303 updateSharedVars(ui); |
|
304 }, |
|
305 stop: function(e, ui) { |
|
306 var children, depthChange = currentDepth - originalDepth; |
|
307 |
|
308 // Return child elements to the list |
|
309 children = transport.children().insertAfter(ui.item); |
|
310 |
|
311 // Update depth classes |
|
312 if( depthChange != 0 ) { |
|
313 ui.item.updateDepthClass( currentDepth ); |
|
314 children.shiftDepthClass( depthChange ); |
|
315 updateMenuMaxDepth( depthChange ); |
|
316 } |
|
317 // Register a change |
|
318 api.registerChange(); |
|
319 // Update the item data. |
|
320 ui.item.updateParentMenuItemDBId(); |
|
321 |
|
322 // address sortable's incorrectly-calculated top in opera |
|
323 ui.item[0].style.top = 0; |
|
324 |
|
325 // handle drop placement for rtl orientation |
|
326 if ( api.isRTL ) { |
|
327 ui.item[0].style.left = 'auto'; |
|
328 ui.item[0].style.right = 0; |
|
329 } |
|
330 |
|
331 // The width of the tab bar might have changed. Just in case. |
|
332 api.refreshMenuTabs( true ); |
|
333 }, |
|
334 change: function(e, ui) { |
|
335 // Make sure the placeholder is inside the menu. |
|
336 // Otherwise fix it, or we're in trouble. |
|
337 if( ! ui.placeholder.parent().hasClass('menu') ) |
|
338 (prev.length) ? prev.after( ui.placeholder ) : api.menuList.prepend( ui.placeholder ); |
|
339 |
|
340 updateSharedVars(ui); |
|
341 }, |
|
342 sort: function(e, ui) { |
|
343 var offset = ui.helper.offset(), |
|
344 edge = api.isRTL ? offset.left + ui.helper.width() : offset.left, |
|
345 depth = api.negateIfRTL * api.pxToDepth( edge - menuEdge ); |
|
346 // Check and correct if depth is not within range. |
|
347 // Also, if the dragged element is dragged upwards over |
|
348 // an item, shift the placeholder to a child position. |
|
349 if ( depth > maxDepth || offset.top < prevBottom ) depth = maxDepth; |
|
350 else if ( depth < minDepth ) depth = minDepth; |
|
351 |
|
352 if( depth != currentDepth ) |
|
353 updateCurrentDepth(ui, depth); |
|
354 |
|
355 // If we overlap the next element, manually shift downwards |
|
356 if( nextThreshold && offset.top + helperHeight > nextThreshold ) { |
|
357 next.after( ui.placeholder ); |
|
358 updateSharedVars( ui ); |
|
359 $(this).sortable( "refreshPositions" ); |
|
360 } |
|
361 } |
|
362 }); |
|
363 |
|
364 function updateSharedVars(ui) { |
|
365 var depth; |
|
366 |
|
367 prev = ui.placeholder.prev(); |
|
368 next = ui.placeholder.next(); |
|
369 |
|
370 // Make sure we don't select the moving item. |
|
371 if( prev[0] == ui.item[0] ) prev = prev.prev(); |
|
372 if( next[0] == ui.item[0] ) next = next.next(); |
|
373 |
|
374 prevBottom = (prev.length) ? prev.offset().top + prev.height() : 0; |
|
375 nextThreshold = (next.length) ? next.offset().top + next.height() / 3 : 0; |
|
376 minDepth = (next.length) ? next.menuItemDepth() : 0; |
|
377 |
|
378 if( prev.length ) |
|
379 maxDepth = ( (depth = prev.menuItemDepth() + 1) > api.options.globalMaxDepth ) ? api.options.globalMaxDepth : depth; |
|
380 else |
|
381 maxDepth = 0; |
|
382 } |
|
383 |
|
384 function updateCurrentDepth(ui, depth) { |
|
385 ui.placeholder.updateDepthClass( depth, currentDepth ); |
|
386 currentDepth = depth; |
|
387 } |
|
388 |
|
389 function initialMenuMaxDepth() { |
|
390 if( ! body[0].className ) return 0; |
|
391 var match = body[0].className.match(/menu-max-depth-(\d+)/); |
|
392 return match && match[1] ? parseInt(match[1]) : 0; |
|
393 } |
|
394 |
|
395 function updateMenuMaxDepth( depthChange ) { |
|
396 var depth, newDepth = menuMaxDepth; |
|
397 if ( depthChange === 0 ) { |
|
398 return; |
|
399 } else if ( depthChange > 0 ) { |
|
400 depth = maxChildDepth + depthChange; |
|
401 if( depth > menuMaxDepth ) |
|
402 newDepth = depth; |
|
403 } else if ( depthChange < 0 && maxChildDepth == menuMaxDepth ) { |
|
404 while( ! $('.menu-item-depth-' + newDepth, api.menuList).length && newDepth > 0 ) |
|
405 newDepth--; |
|
406 } |
|
407 // Update the depth class. |
|
408 body.removeClass( 'menu-max-depth-' + menuMaxDepth ).addClass( 'menu-max-depth-' + newDepth ); |
|
409 menuMaxDepth = newDepth; |
|
410 } |
|
411 }, |
|
412 |
|
413 attachMenuEditListeners : function() { |
|
414 var that = this; |
|
415 $('#update-nav-menu').bind('click', function(e) { |
|
416 if ( e.target && e.target.className ) { |
|
417 if ( -1 != e.target.className.indexOf('item-edit') ) { |
|
418 return that.eventOnClickEditLink(e.target); |
|
419 } else if ( -1 != e.target.className.indexOf('menu-save') ) { |
|
420 return that.eventOnClickMenuSave(e.target); |
|
421 } else if ( -1 != e.target.className.indexOf('menu-delete') ) { |
|
422 return that.eventOnClickMenuDelete(e.target); |
|
423 } else if ( -1 != e.target.className.indexOf('item-delete') ) { |
|
424 return that.eventOnClickMenuItemDelete(e.target); |
|
425 } else if ( -1 != e.target.className.indexOf('item-cancel') ) { |
|
426 return that.eventOnClickCancelLink(e.target); |
|
427 } |
|
428 } |
|
429 }); |
|
430 $('#add-custom-links input[type="text"]').keypress(function(e){ |
|
431 if ( e.keyCode === 13 ) { |
|
432 e.preventDefault(); |
|
433 $("#submit-customlinkdiv").click(); |
|
434 } |
|
435 }); |
|
436 }, |
|
437 |
|
438 /** |
|
439 * An interface for managing default values for input elements |
|
440 * that is both JS and accessibility-friendly. |
|
441 * |
|
442 * Input elements that add the class 'input-with-default-title' |
|
443 * will have their values set to the provided HTML title when empty. |
|
444 */ |
|
445 setupInputWithDefaultTitle : function() { |
|
446 var name = 'input-with-default-title'; |
|
447 |
|
448 $('.' + name).each( function(){ |
|
449 var $t = $(this), title = $t.attr('title'), val = $t.val(); |
|
450 $t.data( name, title ); |
|
451 |
|
452 if( '' == val ) $t.val( title ); |
|
453 else if ( title == val ) return; |
|
454 else $t.removeClass( name ); |
|
455 }).focus( function(){ |
|
456 var $t = $(this); |
|
457 if( $t.val() == $t.data(name) ) |
|
458 $t.val('').removeClass( name ); |
|
459 }).blur( function(){ |
|
460 var $t = $(this); |
|
461 if( '' == $t.val() ) |
|
462 $t.addClass( name ).val( $t.data(name) ); |
|
463 }); |
|
464 }, |
|
465 |
|
466 attachThemeLocationsListeners : function() { |
|
467 var loc = $('#nav-menu-theme-locations'), params = {}; |
|
468 params['action'] = 'menu-locations-save'; |
|
469 params['menu-settings-column-nonce'] = $('#menu-settings-column-nonce').val(); |
|
470 loc.find('input[type="submit"]').click(function() { |
|
471 loc.find('select').each(function() { |
|
472 params[this.name] = $(this).val(); |
|
473 }); |
|
474 loc.find('.spinner').show(); |
|
475 $.post( ajaxurl, params, function(r) { |
|
476 loc.find('.spinner').hide(); |
|
477 }); |
|
478 return false; |
|
479 }); |
|
480 }, |
|
481 |
|
482 attachQuickSearchListeners : function() { |
|
483 var searchTimer; |
|
484 |
|
485 $('.quick-search').keypress(function(e){ |
|
486 var t = $(this); |
|
487 |
|
488 if( 13 == e.which ) { |
|
489 api.updateQuickSearchResults( t ); |
|
490 return false; |
|
491 } |
|
492 |
|
493 if( searchTimer ) clearTimeout(searchTimer); |
|
494 |
|
495 searchTimer = setTimeout(function(){ |
|
496 api.updateQuickSearchResults( t ); |
|
497 }, 400); |
|
498 }).attr('autocomplete','off'); |
|
499 }, |
|
500 |
|
501 updateQuickSearchResults : function(input) { |
|
502 var panel, params, |
|
503 minSearchLength = 2, |
|
504 q = input.val(); |
|
505 |
|
506 if( q.length < minSearchLength ) return; |
|
507 |
|
508 panel = input.parents('.tabs-panel'); |
|
509 params = { |
|
510 'action': 'menu-quick-search', |
|
511 'response-format': 'markup', |
|
512 'menu': $('#menu').val(), |
|
513 'menu-settings-column-nonce': $('#menu-settings-column-nonce').val(), |
|
514 'q': q, |
|
515 'type': input.attr('name') |
|
516 }; |
|
517 |
|
518 $('.spinner', panel).show(); |
|
519 |
|
520 $.post( ajaxurl, params, function(menuMarkup) { |
|
521 api.processQuickSearchQueryResponse(menuMarkup, params, panel); |
|
522 }); |
|
523 }, |
|
524 |
|
525 addCustomLink : function( processMethod ) { |
|
526 var url = $('#custom-menu-item-url').val(), |
|
527 label = $('#custom-menu-item-name').val(); |
|
528 |
|
529 processMethod = processMethod || api.addMenuItemToBottom; |
|
530 |
|
531 if ( '' == url || 'http://' == url ) |
|
532 return false; |
|
533 |
|
534 // Show the ajax spinner |
|
535 $('.customlinkdiv .spinner').show(); |
|
536 this.addLinkToMenu( url, label, processMethod, function() { |
|
537 // Remove the ajax spinner |
|
538 $('.customlinkdiv .spinner').hide(); |
|
539 // Set custom link form back to defaults |
|
540 $('#custom-menu-item-name').val('').blur(); |
|
541 $('#custom-menu-item-url').val('http://'); |
|
542 }); |
|
543 }, |
|
544 |
|
545 addLinkToMenu : function(url, label, processMethod, callback) { |
|
546 processMethod = processMethod || api.addMenuItemToBottom; |
|
547 callback = callback || function(){}; |
|
548 |
|
549 api.addItemToMenu({ |
|
550 '-1': { |
|
551 'menu-item-type': 'custom', |
|
552 'menu-item-url': url, |
|
553 'menu-item-title': label |
|
554 } |
|
555 }, processMethod, callback); |
|
556 }, |
|
557 |
|
558 addItemToMenu : function(menuItem, processMethod, callback) { |
|
559 var menu = $('#menu').val(), |
|
560 nonce = $('#menu-settings-column-nonce').val(); |
|
561 |
|
562 processMethod = processMethod || function(){}; |
|
563 callback = callback || function(){}; |
|
564 |
|
565 params = { |
|
566 'action': 'add-menu-item', |
|
567 'menu': menu, |
|
568 'menu-settings-column-nonce': nonce, |
|
569 'menu-item': menuItem |
|
570 }; |
|
571 |
|
572 $.post( ajaxurl, params, function(menuMarkup) { |
|
573 var ins = $('#menu-instructions'); |
|
574 processMethod(menuMarkup, params); |
|
575 if( ! ins.hasClass('menu-instructions-inactive') && ins.siblings().length ) |
|
576 ins.addClass('menu-instructions-inactive'); |
|
577 callback(); |
|
578 }); |
|
579 }, |
|
580 |
|
581 /** |
|
582 * Process the add menu item request response into menu list item. |
|
583 * |
|
584 * @param string menuMarkup The text server response of menu item markup. |
|
585 * @param object req The request arguments. |
|
586 */ |
|
587 addMenuItemToBottom : function( menuMarkup, req ) { |
|
588 $(menuMarkup).hideAdvancedMenuItemFields().appendTo( api.targetList ); |
|
589 }, |
|
590 |
|
591 addMenuItemToTop : function( menuMarkup, req ) { |
|
592 $(menuMarkup).hideAdvancedMenuItemFields().prependTo( api.targetList ); |
|
593 }, |
|
594 |
|
595 attachUnsavedChangesListener : function() { |
|
596 $('#menu-management input, #menu-management select, #menu-management, #menu-management textarea').change(function(){ |
|
597 api.registerChange(); |
|
598 }); |
|
599 |
|
600 if ( 0 != $('#menu-to-edit').length ) { |
|
601 window.onbeforeunload = function(){ |
|
602 if ( api.menusChanged ) |
|
603 return navMenuL10n.saveAlert; |
|
604 }; |
|
605 } else { |
|
606 // Make the post boxes read-only, as they can't be used yet |
|
607 $('#menu-settings-column').find('input,select').prop('disabled', true).end().find('a').attr('href', '#').unbind('click'); |
|
608 } |
|
609 }, |
|
610 |
|
611 registerChange : function() { |
|
612 api.menusChanged = true; |
|
613 }, |
|
614 |
|
615 attachTabsPanelListeners : function() { |
|
616 $('#menu-settings-column').bind('click', function(e) { |
|
617 var selectAreaMatch, panelId, wrapper, items, |
|
618 target = $(e.target); |
|
619 |
|
620 if ( target.hasClass('nav-tab-link') ) { |
|
621 panelId = /#(.*)$/.exec(e.target.href); |
|
622 if ( panelId && panelId[1] ) |
|
623 panelId = panelId[1] |
|
624 else |
|
625 return false; |
|
626 |
|
627 wrapper = target.parents('.inside').first(); |
|
628 |
|
629 // upon changing tabs, we want to uncheck all checkboxes |
|
630 $('input', wrapper).removeAttr('checked'); |
|
631 |
|
632 $('.tabs-panel-active', wrapper).removeClass('tabs-panel-active').addClass('tabs-panel-inactive'); |
|
633 $('#' + panelId, wrapper).removeClass('tabs-panel-inactive').addClass('tabs-panel-active'); |
|
634 |
|
635 $('.tabs', wrapper).removeClass('tabs'); |
|
636 target.parent().addClass('tabs'); |
|
637 |
|
638 // select the search bar |
|
639 $('.quick-search', wrapper).focus(); |
|
640 |
|
641 return false; |
|
642 } else if ( target.hasClass('select-all') ) { |
|
643 selectAreaMatch = /#(.*)$/.exec(e.target.href); |
|
644 if ( selectAreaMatch && selectAreaMatch[1] ) { |
|
645 items = $('#' + selectAreaMatch[1] + ' .tabs-panel-active .menu-item-title input'); |
|
646 if( items.length === items.filter(':checked').length ) |
|
647 items.removeAttr('checked'); |
|
648 else |
|
649 items.prop('checked', true); |
|
650 return false; |
|
651 } |
|
652 } else if ( target.hasClass('submit-add-to-menu') ) { |
|
653 api.registerChange(); |
|
654 |
|
655 if ( e.target.id && 'submit-customlinkdiv' == e.target.id ) |
|
656 api.addCustomLink( api.addMenuItemToBottom ); |
|
657 else if ( e.target.id && -1 != e.target.id.indexOf('submit-') ) |
|
658 $('#' + e.target.id.replace(/submit-/, '')).addSelectedToMenu( api.addMenuItemToBottom ); |
|
659 return false; |
|
660 } else if ( target.hasClass('page-numbers') ) { |
|
661 $.post( ajaxurl, e.target.href.replace(/.*\?/, '').replace(/action=([^&]*)/, '') + '&action=menu-get-metabox', |
|
662 function( resp ) { |
|
663 if ( -1 == resp.indexOf('replace-id') ) |
|
664 return; |
|
665 |
|
666 var metaBoxData = $.parseJSON(resp), |
|
667 toReplace = document.getElementById(metaBoxData['replace-id']), |
|
668 placeholder = document.createElement('div'), |
|
669 wrap = document.createElement('div'); |
|
670 |
|
671 if ( ! metaBoxData['markup'] || ! toReplace ) |
|
672 return; |
|
673 |
|
674 wrap.innerHTML = metaBoxData['markup'] ? metaBoxData['markup'] : ''; |
|
675 |
|
676 toReplace.parentNode.insertBefore( placeholder, toReplace ); |
|
677 placeholder.parentNode.removeChild( toReplace ); |
|
678 |
|
679 placeholder.parentNode.insertBefore( wrap, placeholder ); |
|
680 |
|
681 placeholder.parentNode.removeChild( placeholder ); |
|
682 |
|
683 } |
|
684 ); |
|
685 |
|
686 return false; |
|
687 } |
|
688 }); |
|
689 }, |
|
690 |
|
691 initTabManager : function() { |
|
692 var fixed = $('.nav-tabs-wrapper'), |
|
693 fluid = fixed.children('.nav-tabs'), |
|
694 active = fluid.children('.nav-tab-active'), |
|
695 tabs = fluid.children('.nav-tab'), |
|
696 tabsWidth = 0, |
|
697 fixedRight, fixedLeft, |
|
698 arrowLeft, arrowRight, resizeTimer, css = {}, |
|
699 marginFluid = api.isRTL ? 'margin-right' : 'margin-left', |
|
700 marginFixed = api.isRTL ? 'margin-left' : 'margin-right', |
|
701 msPerPx = 2; |
|
702 |
|
703 /** |
|
704 * Refreshes the menu tabs. |
|
705 * Will show and hide arrows where necessary. |
|
706 * Scrolls to the active tab by default. |
|
707 * |
|
708 * @param savePosition {boolean} Optional. Prevents scrolling so |
|
709 * that the current position is maintained. Default false. |
|
710 **/ |
|
711 api.refreshMenuTabs = function( savePosition ) { |
|
712 var fixedWidth = fixed.width(), |
|
713 margin = 0, css = {}; |
|
714 fixedLeft = fixed.offset().left; |
|
715 fixedRight = fixedLeft + fixedWidth; |
|
716 |
|
717 if( !savePosition ) |
|
718 active.makeTabVisible(); |
|
719 |
|
720 // Prevent space from building up next to the last tab if there's more to show |
|
721 if( tabs.last().isTabVisible() ) { |
|
722 margin = fixed.width() - tabsWidth; |
|
723 margin = margin > 0 ? 0 : margin; |
|
724 css[marginFluid] = margin + 'px'; |
|
725 fluid.animate( css, 100, "linear" ); |
|
726 } |
|
727 |
|
728 // Show the arrows only when necessary |
|
729 if( fixedWidth > tabsWidth ) |
|
730 arrowLeft.add( arrowRight ).hide(); |
|
731 else |
|
732 arrowLeft.add( arrowRight ).show(); |
|
733 } |
|
734 |
|
735 $.fn.extend({ |
|
736 makeTabVisible : function() { |
|
737 var t = this.eq(0), left, right, css = {}, shift = 0; |
|
738 |
|
739 if( ! t.length ) return this; |
|
740 |
|
741 left = t.offset().left; |
|
742 right = left + t.outerWidth(); |
|
743 |
|
744 if( right > fixedRight ) |
|
745 shift = fixedRight - right; |
|
746 else if ( left < fixedLeft ) |
|
747 shift = fixedLeft - left; |
|
748 |
|
749 if( ! shift ) return this; |
|
750 |
|
751 css[marginFluid] = "+=" + api.negateIfRTL * shift + 'px'; |
|
752 fluid.animate( css, Math.abs( shift ) * msPerPx, "linear" ); |
|
753 return this; |
|
754 }, |
|
755 isTabVisible : function() { |
|
756 var t = this.eq(0), |
|
757 left = t.offset().left, |
|
758 right = left + t.outerWidth(); |
|
759 return ( right <= fixedRight && left >= fixedLeft ) ? true : false; |
|
760 } |
|
761 }); |
|
762 |
|
763 // Find the width of all tabs |
|
764 tabs.each(function(){ |
|
765 tabsWidth += $(this).outerWidth(true); |
|
766 }); |
|
767 |
|
768 // Set up fixed margin for overflow, unset padding |
|
769 css['padding'] = 0; |
|
770 css[marginFixed] = (-1 * tabsWidth) + 'px'; |
|
771 fluid.css( css ); |
|
772 |
|
773 // Build tab navigation |
|
774 arrowLeft = $('<div class="nav-tabs-arrow nav-tabs-arrow-left"><a>«</a></div>'); |
|
775 arrowRight = $('<div class="nav-tabs-arrow nav-tabs-arrow-right"><a>»</a></div>'); |
|
776 // Attach to the document |
|
777 fixed.wrap('<div class="nav-tabs-nav"/>').parent().prepend( arrowLeft ).append( arrowRight ); |
|
778 |
|
779 // Set the menu tabs |
|
780 api.refreshMenuTabs(); |
|
781 // Make sure the tabs reset on resize |
|
782 $(window).resize(function() { |
|
783 if( resizeTimer ) clearTimeout(resizeTimer); |
|
784 resizeTimer = setTimeout( api.refreshMenuTabs, 200); |
|
785 }); |
|
786 |
|
787 // Build arrow functions |
|
788 $.each([{ |
|
789 arrow : arrowLeft, |
|
790 next : "next", |
|
791 last : "first", |
|
792 operator : "+=" |
|
793 },{ |
|
794 arrow : arrowRight, |
|
795 next : "prev", |
|
796 last : "last", |
|
797 operator : "-=" |
|
798 }], function(){ |
|
799 var that = this; |
|
800 this.arrow.mousedown(function(){ |
|
801 var marginFluidVal = Math.abs( parseInt( fluid.css(marginFluid) ) ), |
|
802 shift = marginFluidVal, |
|
803 css = {}; |
|
804 |
|
805 if( "-=" == that.operator ) |
|
806 shift = Math.abs( tabsWidth - fixed.width() ) - marginFluidVal; |
|
807 |
|
808 if( ! shift ) return; |
|
809 |
|
810 css[marginFluid] = that.operator + shift + 'px'; |
|
811 fluid.animate( css, shift * msPerPx, "linear" ); |
|
812 }).mouseup(function(){ |
|
813 var tab, next; |
|
814 fluid.stop(true); |
|
815 tab = tabs[that.last](); |
|
816 while( (next = tab[that.next]()) && next.length && ! next.isTabVisible() ) { |
|
817 tab = next; |
|
818 } |
|
819 tab.makeTabVisible(); |
|
820 }); |
|
821 }); |
|
822 }, |
|
823 |
|
824 eventOnClickEditLink : function(clickedEl) { |
|
825 var settings, item, |
|
826 matchedSection = /#(.*)$/.exec(clickedEl.href); |
|
827 if ( matchedSection && matchedSection[1] ) { |
|
828 settings = $('#'+matchedSection[1]); |
|
829 item = settings.parent(); |
|
830 if( 0 != item.length ) { |
|
831 if( item.hasClass('menu-item-edit-inactive') ) { |
|
832 if( ! settings.data('menu-item-data') ) { |
|
833 settings.data( 'menu-item-data', settings.getItemData() ); |
|
834 } |
|
835 settings.slideDown('fast'); |
|
836 item.removeClass('menu-item-edit-inactive') |
|
837 .addClass('menu-item-edit-active'); |
|
838 } else { |
|
839 settings.slideUp('fast'); |
|
840 item.removeClass('menu-item-edit-active') |
|
841 .addClass('menu-item-edit-inactive'); |
|
842 } |
|
843 return false; |
|
844 } |
|
845 } |
|
846 }, |
|
847 |
|
848 eventOnClickCancelLink : function(clickedEl) { |
|
849 var settings = $(clickedEl).closest('.menu-item-settings'); |
|
850 settings.setItemData( settings.data('menu-item-data') ); |
|
851 return false; |
|
852 }, |
|
853 |
|
854 eventOnClickMenuSave : function(clickedEl) { |
|
855 var locs = '', |
|
856 menuName = $('#menu-name'), |
|
857 menuNameVal = menuName.val(); |
|
858 // Cancel and warn if invalid menu name |
|
859 if( !menuNameVal || menuNameVal == menuName.attr('title') || !menuNameVal.replace(/\s+/, '') ) { |
|
860 menuName.parent().addClass('form-invalid'); |
|
861 return false; |
|
862 } |
|
863 // Copy menu theme locations |
|
864 $('#nav-menu-theme-locations select').each(function() { |
|
865 locs += '<input type="hidden" name="' + this.name + '" value="' + $(this).val() + '" />'; |
|
866 }); |
|
867 $('#update-nav-menu').append( locs ); |
|
868 // Update menu item position data |
|
869 api.menuList.find('.menu-item-data-position').val( function(index) { return index + 1; } ); |
|
870 window.onbeforeunload = null; |
|
871 |
|
872 return true; |
|
873 }, |
|
874 |
|
875 eventOnClickMenuDelete : function(clickedEl) { |
|
876 // Delete warning AYS |
|
877 if ( confirm( navMenuL10n.warnDeleteMenu ) ) { |
|
878 window.onbeforeunload = null; |
|
879 return true; |
|
880 } |
|
881 return false; |
|
882 }, |
|
883 |
|
884 eventOnClickMenuItemDelete : function(clickedEl) { |
|
885 var itemID = parseInt(clickedEl.id.replace('delete-', ''), 10); |
|
886 api.removeMenuItem( $('#menu-item-' + itemID) ); |
|
887 api.registerChange(); |
|
888 return false; |
|
889 }, |
|
890 |
|
891 /** |
|
892 * Process the quick search response into a search result |
|
893 * |
|
894 * @param string resp The server response to the query. |
|
895 * @param object req The request arguments. |
|
896 * @param jQuery panel The tabs panel we're searching in. |
|
897 */ |
|
898 processQuickSearchQueryResponse : function(resp, req, panel) { |
|
899 var matched, newID, |
|
900 takenIDs = {}, |
|
901 form = document.getElementById('nav-menu-meta'), |
|
902 pattern = new RegExp('menu-item\\[(\[^\\]\]*)', 'g'), |
|
903 $items = $('<div>').html(resp).find('li'), |
|
904 $item; |
|
905 |
|
906 if( ! $items.length ) { |
|
907 $('.categorychecklist', panel).html( '<li><p>' + navMenuL10n.noResultsFound + '</p></li>' ); |
|
908 $('.spinner', panel).hide(); |
|
909 return; |
|
910 } |
|
911 |
|
912 $items.each(function(){ |
|
913 $item = $(this); |
|
914 |
|
915 // make a unique DB ID number |
|
916 matched = pattern.exec($item.html()); |
|
917 |
|
918 if ( matched && matched[1] ) { |
|
919 newID = matched[1]; |
|
920 while( form.elements['menu-item[' + newID + '][menu-item-type]'] || takenIDs[ newID ] ) { |
|
921 newID--; |
|
922 } |
|
923 |
|
924 takenIDs[newID] = true; |
|
925 if ( newID != matched[1] ) { |
|
926 $item.html( $item.html().replace(new RegExp( |
|
927 'menu-item\\[' + matched[1] + '\\]', 'g'), |
|
928 'menu-item[' + newID + ']' |
|
929 ) ); |
|
930 } |
|
931 } |
|
932 }); |
|
933 |
|
934 $('.categorychecklist', panel).html( $items ); |
|
935 $('.spinner', panel).hide(); |
|
936 }, |
|
937 |
|
938 removeMenuItem : function(el) { |
|
939 var children = el.childMenuItems(); |
|
940 |
|
941 el.addClass('deleting').animate({ |
|
942 opacity : 0, |
|
943 height: 0 |
|
944 }, 350, function() { |
|
945 var ins = $('#menu-instructions'); |
|
946 el.remove(); |
|
947 children.shiftDepthClass(-1).updateParentMenuItemDBId(); |
|
948 if( ! ins.siblings().length ) |
|
949 ins.removeClass('menu-instructions-inactive'); |
|
950 }); |
|
951 }, |
|
952 |
|
953 depthToPx : function(depth) { |
|
954 return depth * api.options.menuItemDepthPerLevel; |
|
955 }, |
|
956 |
|
957 pxToDepth : function(px) { |
|
958 return Math.floor(px / api.options.menuItemDepthPerLevel); |
|
959 } |
|
960 |
|
961 }; |
|
962 |
|
963 $(document).ready(function(){ wpNavMenu.init(); }); |
|
964 |
|
965 })(jQuery); |