Django admin, display actions as buttons - django

In Django admin, there is a drop down list for actions.
What I want to achieve is to get rid of the drop down list, and 'Go' button, and instead, display my actions as buttons.
How can it be done? Thanks in advance.

Create a js file action_buttons.js inside your static directory
(function ($) {
function fix_actions() {
var container = $('div.actions');
if (container.find('option').length < 10) {
container.find('label, button').hide();
var buttons = $('<div></div>')
.prependTo(container)
.css('display', 'inline')
.addClass('class', 'action-buttons');
container.find('option:gt(0)').each(function () {
$('<button>')
.appendTo(buttons)
.attr('name', this.value)
.addClass('button')
.text(this.text)
.click(function () {
container.find('select')
.find(':selected').attr('selected', '').end()
.find('[value=' + this.name + ']').attr('selected', 'selected');
$('#changelist-form button[name="index"]').click();
});
});
}
};
$(function () {
fix_actions();
});
})(django.jQuery);
Copy above code to js file
In you admin.py under admin class add
class Media:
js = ('path/to/action_buttons.js', )

Related

Persistent AdminLTE sidebar state

I've inherited some work on an AdminLTE sidebar on a Django website. The page in question uses an "extends" block to load AdminLTE's index.html page right off the bat. Links on our treeview sidebar cause the entire page to reload, including the sidebar, so the state of any expanded treeview menus is lost whenever someone clicks a link.
I'm guessing there's some well-known way of making the sidebar keep its treeview menus open, but I've yet to find it. There are some working examples on the AdminLTE site, but I can't figure out how they work.
Can someone point me to the right piece of documentation to help me make my sidebar persistent across page loads?
Treeview css class works in an unordered list so any child links only show up when the parent list is clicked. An example of this is if you have "home" and then "About" "About-Locations". When you click About it is a tree-view class and on the sidebar it will show locations underneath it. When you click on home the locations sidebar link will not be displayed as this is how the css is written for the list.
The code can be found in the "AdminLTE.css" file.
I'm not working on django, I work on a MVC Razor app.
For the same problem, I use this solution :
I store the link clicked on the menu (ajax send to the server and session storage, but you can use cookie or what you want).
The link clicked is inserted in the java script below :
$(" ul.treeview-menu > li > a").on("click", function ()
{
if (this.href == "#")
return;
$.ajax({
type: "POST",
url: '/Outils/SetActiveMenu',
data: { url: this.href },
dataType: "json"
});
})
$(document).ready(function () {
var v = "#Html.Raw(Session["ActiveMenu"] == null?"": Session["ActiveMenu"].ToString())";
if(v == "") return;
var a = $('a[href="' + v + '"]');
openParentMenu(a);
a.css("background-color", "#E3E6E5");
});
function openParentMenu(item)
{
var parent = item.parent().closest("li.treeview");
if (parent.length != 0) {
openParentMenu(parent);
parent[0].children.item("a").click();
}
}
Here is the code for reference.
/* Tree()
* ======
* Converts the sidebar into a multilevel
* tree view menu.
*
* #type Function
* #Usage: $.AdminLTE.tree('.sidebar')
*/
$.AdminLTE.tree = function (menu) {
var _this = this;
var animationSpeed = $.AdminLTE.options.animationSpeed;
$(menu).on('click', 'li a', function (e) {
//Get the clicked link and the next element
var $this = $(this);
var checkElement = $this.next();
//Check if the next element is a menu and is visible
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {
//Close the menu
checkElement.slideUp(animationSpeed, function () {
checkElement.removeClass('menu-open');
//Fix the layout in case the sidebar stretches over the height of the window
//_this.layout.fix();
});
checkElement.parent("li").removeClass("active");
}
//If the menu is not visible
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {
//Get the parent menu
var parent = $this.parents('ul').first();
//Close all open menus within the parent
var ul = parent.find('ul:visible').slideUp(animationSpeed);
//Remove the menu-open class from the parent
ul.removeClass('menu-open');
//Get the parent li
var parent_li = $this.parent("li");
//Open the target menu and add the menu-open class
checkElement.slideDown(animationSpeed, function () {
//Add the class active to the parent li
checkElement.addClass('menu-open');
parent.find('li.active').removeClass('active');
parent_li.addClass('active');
//Fix the layout in case the sidebar stretches over the height of the window
_this.layout.fix();
});
}
//if this isn't a link, prevent the page from being redirected
if (checkElement.is('.treeview-menu')) {
e.preventDefault();
}
});
};
I have used the inbuilt functionality mentioned by #MDT and have created a function:
function toggleCollapsibleList(){
//Get the clicked link and the next element
var $this = $('#parent-list-item-id');
var checkElement = $('#an-id-for-collapsible-li-with-treeview-class');
//Check if the next element is a menu and is visible
if ((checkElement.is('.treeview-menu')) && (checkElement.is(':visible')) && (!$('body').hasClass('sidebar-collapse'))) {
//Close the menu
checkElement.slideUp(500, function () {
checkElement.removeClass('menu-open');
//Fix the layout in case the sidebar stretches over the height of the window
//_this.layout.fix();
});
checkElement.parent("li").removeClass("active");
}
//If the menu is not visible
else if ((checkElement.is('.treeview-menu')) && (!checkElement.is(':visible'))) {
//Get the parent menu
var parent = $this.parents('ul').first();
//Close all open menus within the parent
var ul = parent.find('ul:visible').slideUp(500);
//Remove the menu-open class from the parent
ul.removeClass('menu-open');
//Get the parent li
var parent_li = $this.parent("li");
//Open the target menu and add the menu-open class
checkElement.slideDown(500, function () {
//Add the class active to the parent li
checkElement.addClass('menu-open');
parent.find('li.active').removeClass('active');
parent_li.addClass('active');
//Fix the layout in case the sidebar stretches over the height of the window
});
}}
This worked for me :)

Ionic2 SearchBar confusion, onInput called after firing onClear, onCancel

I have been following the tutorial at ionic2 SearchBar to work on the filter functionality.
The question is, I am not able to figure out how to get onCancel and onClear to work.
Steps:
1) Enter some keywords in SearchBar. It calls the onInput event and I get the value from searchItem.target.value unlike in tutorial which just uses searchItem.value
2) Now i try to click on clear "x" or Cancel button and it calls the onClear/onCancel event which is immediately followed by onInput event. And during this call, it does not find the searchItem.target.value and results in undefined due to which it breaks the functionality.
Can anyone provide more in depth details on how this works?
i fixed it in tutorial sample for ionic2 by stopping onClear event propagation
import {Component} from '#angular/core';
#Component({
selector: 'my-search',
template: '<ion-toolbar primary><ion-searchbar (input)="onInput($event)" (ionClear)="onClear($event)"></ion-searchbar></ion-toolbar><ion-content><ion-list><ion-item *ngFor="let item of items">{{ item }}</ion-item></ion-list></ion-content>'
})
export class HomePage {
items = [];
constructor() {
this.initializeItems();
}
initializeItems() {
this.items = [
'Angular 1.x',
'Angular 2',
'ReactJS',
'EmberJS',
'Meteor',
'Typescript',
'Dart',
'CoffeeScript'
];
}
onClear(ev)
{
this.initializeItems();
ev.stopPropagation();
}
onInput(ev) {
// Reset items back to all of the items
this.initializeItems();
// set val to the value of the searchbar
var val = ev.target.value;
// if the value is an empty string don't filter the items
if (val && val.trim() != '') {
this.items = this.items.filter((item) => {
return (item.toLowerCase().indexOf(val.toLowerCase()) > -1);
})
}
}
}

How to prevent multiple firing on click events

Hi have a bootstrap lightbox (ekko lightbox) that loads a gallery by data-remote attributes. My problemi is that i have loaded a modal footer by data attributes. In my footer I have added a button identified by id="submit". Then I have associated to this button a click action that ia used for send the file name to a PHP page by an ajax request. My action is loaded like this $(document).on("click", "#submit", function(){/* my ajax call */}); now if the popup modal is shown n times, the ajax request is sent n times. How i fix this issue?
I have te same problem. I can't resolve this, but i did the following code to "fix" this problem:
$(".glyphicon-picture").click(function() {
setTimeout(function (){
var a = [];
for (i = 0; i <= 1000; i++){
if ($("#ekkoLightbox-"+i).attr("id") != undefined) a.push($("#ekkoLightbox-"+i).attr("id"));
}
for (i = 1; i < a.length; i++){
$("#"+a[i]).remove();
}
$(".ekko-lightbox").on("hidden.bs.modal", function () {
$(".modal-backdrop").remove();
});
}, 750);
})

Refresh a Grid using dojo

I want to refresh a dojo grid in my web page. I tried .refresh which is given in dojotoolkit.org without success. is there any other convenient way to do refreshing? Thanks in advance.
Maybe this helps. This is the way i refresh my Grid:
if(!registry.byId("GraphGrid")){
var grid = new EnhancedGrid({
id: 'GraphGrid',
store: GraphicStore,
query: { ident: "*" },
structure: layout,
rowSelector: '20px',
plugins: {
indirectSelection: {
headerSelector:true,
width:"40px",
styles:"text-align: center;"
}}
},"GridGraphicInMap");
/*Call startup() to render the grid*/
grid.startup();
dojo.connect(grid, "onRowClick", grid, function(evt){
var idx = evt.rowIndex,
item = this.getItem(idx);
// get a value out of the item
var value = this.store.getValue(item, "geom");
highlightGeometry(value,true);
// do something with the value.
});
}
else {
registry.byId("GraphGrid").setStore(GraphicStore);
}
When i first call my function the grid is generated. Evrytime i call the function later only the store is refreshed.
Regards, Miriam

On/Off icon for boolean field in list_editable modelAdmin

When I put my boolean field in list_editable, it's icon change from the nice on/off icon to the legacy checkbox. Is there a way to keep the field editable with the nice icons ?
I think I've already done this, but can't remember how...
Use you own JavaScript to replace the checkbox with the appropriate image, and use click events to change the image and set the checkbox appropriately.
CSS
.hidden {
position:absolute;
left:-99999px;
width:0;
height:0;
overflow:hidden;
}
JS
(function($){
var on_image = '/static/admin/img/admin/icon-yes.gif';
var off_image = '/static/admin/img/admin/icon-no.gif';
$(document).ready(function(){
var $checkbox = $('.checkbox_field input');
// Can't simply `hide()` as its value will not be posted
$checkbox.addClass('hidden');
var $img = $('<img/>');
if ($checkbox.attr('checked')) {
$img.attr('href', on_image);
$img.attr('alt', 'On');
} else {
$img.attr('href', off_image);
$img.attr('alt', 'Off');
}
$img.insertAfter($checkbox);
$img.click(function(){
var $img = $(this);
var $checkbox = $img.siblings('input');
if ($img.attr('href') == on_image) {
$img.attr('href', off_image);
$img.attr('alt', 'Off');
$checkbox.attr('checked', false);
} else {
$img.attr('href', on_image);
$img.attr('alt', 'On');
$checkbox.attr('checked', true);
}
});
});
)(django.jQuery);