Skip to content

Instantly share code, notes, and snippets.

@jaredwilli
Created February 10, 2011 14:48
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jaredwilli/820633 to your computer and use it in GitHub Desktop.
Save jaredwilli/820633 to your computer and use it in GitHub Desktop.
WordPress navmenu sortable drag/drop script unpacked
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)
}
}
}
}
}
}
})
},
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").attr("disabled", "disabled").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.attr("checked", "checked")
}
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>&laquo;</a></div>');
d = b('<div class="nav-tabs-arrow nav-tabs-arrow-right"><a>&raquo;</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);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment