Modify DataTables Button Action - javascript

I want to add the search keyword to the URL of a custom button action element in order to pass the keyword as a GET parameter.
I am initializing the data table like so:
var table = $('#list').DataTable( {
dom: 'lBfrtip',
buttons: [
{
text: 'Export to PDF',
className: 'export-to-pdf',
action: function ( e, dt, button, config ) {
window.open('generate_pdf.php?case_id=<?= $case_id? ?>','_blank');
}
And attempting to append the keyword to the URL using:
// append keyword search values to pdf url
$('#list').on('search.dt', function() {
var keyword = $('.dataTables_filter input').val();
//FAILS HERE
var export_pdf_url = $(".export-to-pdf").attr("href");
// remove keywords if they already exist
removeURLParameter(export_pdf_url, 'keyword');
// append filter value to filtered pdf href
$(".export-to-pdf").attr("href", export_pdf_url + '&keyword='+keyword);
});
This seems to be failing because the action function is not actually assigning the the button a href attribute.
Any suggestions on how to dynamically modify the action function or other approaches would be very much appreciated.

Use search() API method which returns currently applied global search when called without arguments.
Then generate URL directly in the callback function for action option.
For example:
buttons: [
{
text: 'Export to PDF',
className: 'export-to-pdf',
action: function ( e, dt, button, config ) {
var query = dt.search();
window.open('generate_pdf.php?case_id=<?= $case_id? ?>&keyword=' + encodeURIComponent(query), '_blank');
}
}
],

Related

Getting the selected value on autocomplete in Jquery

I added an Autocomplete feature to a form on a HTML template, i would like to perform some actions when an hint is selected, is there any way to do it? I'm using Jquery-Typeahead. Here is my actual code:
$(document).ready(function(){
// Defining the local dataset
$.getJSON('http://127.0.0.1:8000/myapi', function(data) {
console.log(data)
var dt = data
$(() => {
$('#myform').typeahead({
source: {
data: dt.results.map(record => record.item)
},
callback: {
onInit: function($el) {
console.log(`Typeahead initiated on: ${$el.prop('tagName')}#${$el.attr('id')}`);
},
onClick: function() {
console.log(); //How can i console.log() the selected value here, for example?
}
}
});
});
});
});
Try defining an onClickAfter callback, it's called right after user clicks on an item. Something like this:
onClickAfter: function(node, a, item, event) {
// item will be the item you selected
console.log(item);
}
You can also define the onClickBefore callback the same way, and it will be called immediately before "normal" typeahead behaviour kicks in

Odoo field doesn't update when changed from javascript with an RPC call

I want to be able to change the context of a one2many field (work_unit) programatically to modify the default value of one of its fields (product_id).
Ideally I would like to change the o2m context directly from my widget, but I haven't had any success doing that, the view doesn't acknowledge any changes I make from javascript.
Current approach: I have another field selected_chapter which I pass through context as the default for work_unit.product_id. This works fine: when I change selected_chapter manually, the o2m context picks up the new default for the field product_id.
Now, I want to be able to modify selected_chapter programatically from a widget in javascript.
I do this by calling a python method with an _rpc() call from my widget, and it works, but the view doesn't update selected_chapter until I save the record which defeats the purpose of the call.
Widget code:
ListRenderer.include({
...
_setSelectedChapter: function () {
var self = this;
this.trigger_up('mutexify', {
action: function () {
return self._rpc({
model: 'sale.order',
method: 'set_selected_chapter',
args: [
[self.res_id]
],
kwargs: {
chapter_id: self.filter.getSelected()
},
}).then(function (result) {
console.log("res", result);
self._render();
});
},
});
},
...
})
Model code:
selected_chapter = fields.Many2one('product.product')
#api.multi
def set_selected_chapter(self, chapter_id):
chapter = self.env['product.product'].browse(chapter_id)
if not chapter.exists():
return
# I've also tried using self.update(), same results
self.selected_chapter = chapter
View code:
<field name="work_unit" mode="tree,kanban" filter_field="product_id" context="{'default_product_id': selected_chapter}">
First, rename work_unit to work_unit_ids.
Then, on the server side write an onchange method. See https://www.odoo.com/documentation/12.0/reference/orm.html#onchange-updating-ui-on-the-fly

CKEDITOR: Disable plugin button when text is not highlighted

I have a CKEDITOR plugin that I'm having trouble disabling when there is no selected copy in the editor. Right now, the user can click the button without any highlighted text in the editor. I would like to modify it so that the plugin button is only active when there is copy highlighted in the editor. I've followed the suggestion here, but it isn't working.
Main Plugin Code:
CKEDITOR.plugins.add('cta', {
icons: 'cta',
init: function (editor) {
// Funciton depending on editor selection (taken from the scope) will set the state of our command.
function RefreshState() {
console.log('RefreshState');
var editable = editor.editable(),
// Command that we want to control.
command = editor.getCommand('source'),
range,
commandState;
if (!editable) {
// It might be a case that editable is not yet ready.
console.log("editable not ready yet");
return;
}
// We assume only one range.
range = editable.getDocument().getSelection().getRanges()[0];
console.log(`range: `);
console.log(range);
// The state we're about to set for the command.
commandState = (range && !range.collapsed) ? CKEDITOR.TRISTATE_OFF : CKEDITOR.TRISTATE_DISABLED;
console.log('commandState');
console.log(commandState);
command.setState(commandState);
}
// We'll use throttled function calls, because this event can be fired very, very frequently.
var throttledFunction = CKEDITOR.tools.eventsBuffer(250, RefreshState);
// Now this is the event that detects all the selection changes.
editor.on('selectionCheck', throttledFunction.input);
// You'll most likely also want to execute this function as soon as editor is ready.
editor.on('instanceReady', function (evt) {
// Also do state refresh on instanceReady.
RefreshState();
});
editor.addCommand('ctabtn', new CKEDITOR.dialogCommand('ctaDialog'));
editor.ui.addButton('cta', {
label: 'Insert Call to Action button',
command: 'ctabtn',
toolbar: 'insert'
});
CKEDITOR.dialog.add('ctaDialog', this.path + 'dialogs/cta.js');
}
});
My dialog code is here:
CKEDITOR.dialog.add('ctaDialog', function (editor) {
return {
// Basic properties of the dialog window: title, minimum size.
title: 'Call to Action',
minWidth: 400,
minHeight: 200,
// Dialog window content definition.
contents: [{
// Definition of the Basic Settings dialog tab (page).
id: 'tab-basic',
label: 'Basic Settings',
// The tab content.
elements: [{
// Text input field for the Call to Action text.
type: 'text',
id: 'cta',
label: 'Call to Action',
// Validation checking whether the field is not empty.
validate: CKEDITOR.dialog.validate.notEmpty("Call to Action field cannot be empty.")
},
{
// Text input field for the link text.
type: 'text',
id: 'url',
label: 'URL',
// Validation checking whether the field is not empty.
validate: CKEDITOR.dialog.validate.notEmpty("URL field cannot be empty.")
}
]
}],
// method invoked when the dialog button is clicked
onShow: function () {
var element = editor.getSelection();
var link = CKEDITOR.plugins.link;
var _this = this.getParentEditor();
var CTAhref = link.getSelectedLink(_this);
this.setValueOf('tab-basic', 'cta', element.getSelectedText().toString());
if (CTAhref != '' && CTAhref !== null) {
this.setValueOf('tab-basic', 'url', CTAhref.$.href);
}
},
// This method is invoked once a user clicks the OK button, confirming the dialog.
onOk: function () {
var dialog = this;
var CTA = editor.document.createElement('a');
CTA.setAttribute('href', dialog.getValueOf('tab-basic', 'url'));
CTA.setAttribute('class', 'btn btn-special--lg');
CTA.setText(dialog.getValueOf('tab-basic', 'cta'));
editor.insertElement(CTA);
}
};
});
Any ideas on why the plugin icon button on the toolbar doesn't become inactive when there is no copy highlighted in the editor? I can see in the console that CKEDITOR.dom.range.collapsed is toggling between TRUE/FALSE depending upon whether text is highlighted or not. It's just not disabling the button.
As stated, the suggested way of handling this was not working for me. What was working was using range.collapsed in returning a true value if a selection was made in the editor. With that, I turned to using Jquery to handle the rest.
// Hacky. But it gets the job done.
// a.cke_button.cke_button__cta.cke_button_off is the selector for my toolbar button.
// The onclick function listed was pulled from looking at the CKeditor functions
// to initiate my plugins modal.
// The setting of the "onclick" prop to null is needed to override the modal onclick
// binding when there is no selection.
range = editable.getDocument().getSelection().getRanges()[0];
if (range.collapsed === false) {
$('a.cke_button.cke_button__cta.cke_button_off').attr("onclick", 'CKEDITOR.tools.callFunction(83,this);return false;');
$('a.cke_button__cta').toggleClass('cta_button_disabled');
} else {
$('a.cke_button.cke_button__cta.cke_button_off').prop("onclick", null);
}

How to update/add buttons once instantiated datatables

I am new to JavaScript and I lack knowledge javascript objects.
I would like to know how I can add the extension of the datatable 1.10 button once created .
My code is:
var table;
$('#MyDiv').DataTable({someCode;});
$.fn.dataTable.ext.buttons.ok = {
text: 'OK',
action: function (e, dt, node, config) {
console.log("Hi");
}
};
table = $('#MyDiv').DataTable();
//!Here I want to add my button in table var!
Option 1
The easiest way to do it (in my opinion) is to use the option form of the button declaration, instead of the function form you are attempting to use here. In your case, that would look something like this:
table = $('#MyDiv').DataTable({
/*Other DataTables config options go here*/
buttons: [
{
text: 'OK',
action: function ( e, dt, node, config ) {
console.log("Hi");
}
}
]
});
This can be found in the DataTables examples, which is a great source for DataTables information.
Option 2
If instead you wish to keep using the function notation, then you would simply have to add a button declaration to the options instead of the whole action/text block that is there in the above example. See below:
var table;
//You should not have 2 .DataTable() calls, so I removed this one
//Move any other options you had to the other call below
$.fn.dataTable.ext.buttons.ok = {
text: 'OK',
action: function (e, dt, node, config) {
console.log("Hi");
}
};
table = $('#MyDiv').DataTable({
/*Other DataTables config options go here*/
buttons: [
'ok'
]
});
Either way should work, it just depends on how you prefer to organize your code.
I'd also refer you to the custom buttons documentation on the DataTables website to get more information or to see where I got these code blocks from.

Pass Id to a Onclick Function JQGrid

I have a JQGrid.I need to take some Id to the OnClick function.In my scenario i wanted to get BasicId to the OnClick function.
MyCode
function grid() {
//JqGrid
$('#griddata').html('<table class="table" id="jqgrid"></table>')
$('#jqgrid').jqGrid({
url: '/Admin/GetBasicData/',
datatype: 'json',
mtype: 'GET',
//columns names
colNames: ['BasicId','Images'],
//columns model
colModel: [
{ name: 'BasicId', index: 'BasicId', resizable: false },
{
name: 'Images',
width: 120,
formatter: function () {
return "<button class='btn btn-warning btn-xs' onclick='OpenDialog()' style='margin-left:30%'>View</button>";
}
},
//Some Code here
Open Dialog Function
function OpenDialog(BasicId)
{
//Some code here
}
You can use onclick='OpenDialog.call(this, event)' instead of onclick='OpenDialog()'. You will have this inside of OpenDialog initialized to the clicked <button> and the event.target. Thus your code could be like the following
function OpenDialog (e) {
var rowid = $(this).closest("tr.jqgrow").attr("id"),
$grid = $(this).closest(".ui-jqgrid-btable"),
basicId = $grid.jqGrid("getCell", rowid, "BasicId");
// ...
e.stopPropagation();
}
One more option is even better: you don't need to specify any onclick. Instead of that you can use beforeSelectRow callback of jqGrid:
beforeSelectRow (rowid, e) {
var $td = $(e.target).closest("td"),
iCol = $.jgrid.getCellIndex($td[0]),
colModel = $(this).jqGrid("getGridParam", "colModel"),
basicId = $(this).jqGrid("getCell", rowid, "BasicId");
if (colModel[iCol].name === "Images") { // click in the column "Images"
// one can make additional test for
// if (e.target.nodeName.toUpperCase() === "button")
// to be sure that it was click to the button
// and not the click on another part of the column
OpenDialog(rowid);
return false; // don't select the row - optional
}
}
The main advantages of the last approach: one don't need to make any additional binding (every binding get memory resources and it take time). There are already exist on click handler in the grid and one can use it. It's enough to have one click handler because of event bubbling. The e.target provide us still full information about the clicked element.
Writing js event in your buttons html is not a good idea, its against 'un-obtrusive javasript' principle. You can instead add a click event on the entire grid in the render function and in the callback, filter out based on whether the button was clicked.
//not sure of the syntax of jqgrid, but roughly:
render: function(){
$('#jqgrid').unbind('click').on('click', function(){
if($(e.target).hasClass('btn-warning')){
var tr = $(e.target).parent('tr');
//retrieve the basicId from 'tr'
OpenDialog(/*pass the basicId*/)
}
})
}

Categories

Resources