253 lines
9.4 KiB
JavaScript
253 lines
9.4 KiB
JavaScript
var grappelli = {};
|
|
|
|
(function($) {
|
|
grappelli.collapseHandlerClass = "collapse-handler";
|
|
grappelli.collapsedBlockedClass = "collapse-blocked";
|
|
grappelli.openAllClass = "open-handler";
|
|
grappelli.closeAllClass = "close-handler";
|
|
grappelli.collapseClass = "collapse";
|
|
grappelli.closedClass = "closed";
|
|
grappelli.openClass = "open";
|
|
|
|
|
|
/**
|
|
* if collapsible in menu is opened it has to close if it "looses focus"
|
|
*/
|
|
grappelli.collapseBlurHandler = function(evt) {
|
|
var that = $(this),
|
|
parents = $(evt.originalEvent.explicitOriginalTarget).parents(),
|
|
handler_parent = that.parents("ul.navigation-menu")[0] || that.parents("ul#user-tools")[0];
|
|
for (var i = 0; i < parents.length; i++) {
|
|
if (parents[i] == handler_parent) {
|
|
var target = evt.originalEvent.explicitOriginalTarget;
|
|
if (target.nodeType == 3) {
|
|
target = $(target).parent()
|
|
} else {
|
|
target = $(target);
|
|
}
|
|
target.one('blur', grappelli.collapseBlurHandler);
|
|
return;
|
|
}
|
|
}
|
|
that.parents("." + grappelli.collapseClass).first()
|
|
.toggleClass(grappelli.closedClass)
|
|
.toggleClass(grappelli.openClass);
|
|
};
|
|
|
|
/**
|
|
* handles assignment of classes (open/close) when collapse handler is clicked
|
|
* NOTE: special case if collapsible is within the header menu
|
|
*/
|
|
grappelli.collapseHandler = function() {
|
|
if (!$("body").hasClass(grappelli.collapsedBlockedClass)) {
|
|
var that = $(this);
|
|
that.parents("." + grappelli.collapseClass).first()
|
|
.toggleClass(grappelli.closedClass)
|
|
.toggleClass(grappelli.openClass);
|
|
|
|
// close again on blur if it's an menu dropdown from the header (i.e. bookmarks)
|
|
if (that.parent(".menu-item").length || that.parent(".user-options-container").length) {
|
|
menu = $(this).parent('li').children('ul');
|
|
menumaxheight = $(window).height() - 80;
|
|
menuheight = menu.height();
|
|
if (menumaxheight < menuheight) {
|
|
$(menu).css({
|
|
"max-height": menumaxheight,
|
|
"overflow-y": "scroll"
|
|
});
|
|
}
|
|
|
|
that.one('blur', grappelli.collapseBlurHandler);
|
|
}
|
|
}
|
|
return false;
|
|
};
|
|
|
|
grappelli.addCollapseHandlerClass = function() {
|
|
$("." + this.collapseClass).each(function() {
|
|
var node = $(this).children().first();
|
|
if (node.is("h2") || node.is("h3") || node.is("h4")) {
|
|
node.addClass(grappelli.collapseHandlerClass)
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* add click handler to collapsibles
|
|
* NOTE: secial case for collapse handler in menu
|
|
*/
|
|
grappelli.registerCollapseHandler = function() {
|
|
$("." + this.collapseHandlerClass).click(this.collapseHandler);
|
|
|
|
// if the item has children you generally open the cildren with the button next to it.
|
|
// open the menu anyways if it has an empty link
|
|
$('a.parent.item-collapse-handler-container').click(function(){
|
|
var that = $(this);
|
|
|
|
if (that.attr('href') == "#") {
|
|
that.next().click();
|
|
}
|
|
});
|
|
|
|
// do this each time a submenu is opened
|
|
$('ul.navigation-menu a.item-collapse-handler').click(function(){
|
|
// Collapse
|
|
$(this).closest('li.item-collapse').toggleClass("item-closed").toggleClass("item-open");
|
|
// Calculate Menu Height
|
|
menu = $(this).closest('ul.navigation-menu>li>ul');
|
|
$(menu).removeAttr("style");
|
|
menumaxheight = $(window).height() - 80;
|
|
menuheight = menu.height();
|
|
menuwidth = menu.outerWidth() + 15;
|
|
if (menumaxheight < menuheight) {
|
|
// $(menu).addClass("");
|
|
$(menu).css({
|
|
"width": menuwidth,
|
|
"height": menuheight,
|
|
"max-height": menumaxheight,
|
|
"overflow-y": "scroll",
|
|
"overflow-x": "hidden !important"
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
grappelli.registerOpenAllHandler = function() {
|
|
$("." + this.openAllClass).click(this.openAllHandler);
|
|
};
|
|
|
|
/*
|
|
* Open all
|
|
*/
|
|
grappelli.openAllHandler = function() {
|
|
// get .group and not .collapse because it doesn't necessarily have .collapse
|
|
$(this).parents(".group")
|
|
.removeClass(grappelli.closedClass)
|
|
.addClass(grappelli.openClass)
|
|
.find("." + grappelli.collapseClass)
|
|
.removeClass(grappelli.closedClass)
|
|
.addClass(grappelli.openClass);
|
|
};
|
|
|
|
grappelli.registerCloseAllHandler = function() {
|
|
$("." + this.closeAllClass).click(this.closeAllHandler);
|
|
};
|
|
|
|
/*
|
|
* Close all
|
|
*/
|
|
grappelli.closeAllHandler = function() {
|
|
// get .group and not .collapse because it doesn't necessarily have .collapse
|
|
$(this).parents(".group")
|
|
.find("." + grappelli.collapseClass)
|
|
.removeClass(grappelli.openClass)
|
|
.addClass(grappelli.closedClass);
|
|
};
|
|
|
|
grappelli.initCollapsible = function() {
|
|
grappelli.addCollapseHandlerClass();
|
|
grappelli.registerCollapseHandler();
|
|
|
|
grappelli.registerOpenAllHandler();
|
|
grappelli.registerCloseAllHandler();
|
|
|
|
$("." + grappelli.collapseClass + " ul.errorlist").each(function() {
|
|
$(this).parents("." + grappelli.collapseClass)
|
|
.removeClass(grappelli.closedClass)
|
|
.addClass(grappelli.openClass);
|
|
});
|
|
};
|
|
|
|
grappelli.getFormat = function(type) {
|
|
if (type == "date") {
|
|
var format = DATE_FORMAT.toLowerCase().replace(/%\w/g, function(str) {
|
|
str = str.replace(/%/, '');
|
|
return str + str;
|
|
});
|
|
}
|
|
return format;
|
|
}
|
|
|
|
grappelli.initDateAndTimePicker = function() {
|
|
var options = {
|
|
//appendText: '(mm/dd/yyyy)',
|
|
showOn: 'button',
|
|
buttonImageOnly: false,
|
|
buttonText: '',
|
|
dateFormat: grappelli.getFormat('date'),
|
|
showButtonPanel: true,
|
|
showAnim: '',
|
|
// HACK: sets the current instance to a global var.
|
|
// needed to actually select today if the today-button is clicked.
|
|
// see onClick handler for ".ui-datepicker-current"
|
|
beforeShow: function(year, month, inst) {
|
|
grappelli.datepicker_instance = this;
|
|
}
|
|
};
|
|
var dateFields = $("input[class*='vDateField']:not([id*='__prefix__'])");
|
|
dateFields.datepicker(options);
|
|
|
|
if (typeof IS_POPUP != "undefined" && IS_POPUP) {
|
|
dateFields.datepicker('disable');
|
|
}
|
|
|
|
// HACK: adds an event listener to the today button of datepicker
|
|
// if clicked today gets selected and datepicker hides.
|
|
// user live() because there is no hoock after datepicker generates it's complete dom.
|
|
$(".ui-datepicker-current").live('click', function() {
|
|
$.datepicker._selectDate(grappelli.datepicker_instance);
|
|
grappelli.datepicker_instance = null;
|
|
})
|
|
|
|
// inti timepicker
|
|
$("input[class*='vTimeField']:not([id*='__prefix__'])").timepicker();
|
|
};
|
|
|
|
grappelli.initHacks = function() {
|
|
// to get rid of text after DateField (hardcoded in django.admin)
|
|
$('p.datetime').each(function() {
|
|
var text = $(this).html();
|
|
text = text.replace(/^\w*: /, "");
|
|
text = text.replace(/<br>.*: /, "<br>");
|
|
$(this).html(text);
|
|
});
|
|
};
|
|
|
|
grappelli.initSearchbar = function() {
|
|
var searchbar = $("input#searchbar");
|
|
// var searchbar = $("input#searchbar"),
|
|
// searchbar_tooltip = $('div#searchbar_tooltip');
|
|
// if (searchbar_tooltip.length == 0) return;
|
|
|
|
searchbar.focus();
|
|
|
|
// searchbar.bind('keydown', function() {
|
|
// searchbar_tooltip.hide();
|
|
// });
|
|
// searchbar.bind("mouseover", function() {
|
|
// searchbar_tooltip.show();
|
|
// });
|
|
// searchbar.bind("mouseout", function() {
|
|
// searchbar_tooltip.hide();
|
|
// });
|
|
};
|
|
|
|
// Using window.load instead of document ready for better performances
|
|
// It prevents lots of glitches, like divs that moves around upon loading
|
|
//
|
|
// Use $(document).ready only if you have to deal with images since it will
|
|
// wait for the document to be fully loaded/rendered before running the function
|
|
// while window.load method will run as soon as the DOM/CSS is loaded.
|
|
|
|
$(window).load(function() {
|
|
// we do the hacks first!
|
|
// because we manipulate dom via innerHTML => loose events
|
|
grappelli.initHacks();
|
|
grappelli.initCollapsible();
|
|
grappelli.initDateAndTimePicker();
|
|
grappelli.initSearchbar();
|
|
|
|
// add something for clicking outside the navigation-menu
|
|
});
|
|
})(django.jQuery);
|