Shiny.onInput - react on every click JS - javascript

probably quite easy question. I am not too familiar with Javascript embedded in Shiny items and cannot get this one right
I have a gVis table and the only way to get the row selected is to use a js listener. My listener is quite easy, assigning a row to a variable (here sustable)
sussimilar_click <- sprintf("var sustable = chart.getSelection()[0]['row'];
Shiny.onInputChange('sustable', sustable);")
what i want to achieve is to alter the table beneath - changing the value from TRUE to FALSE and the other way with every click
so i have a simple observer
observe({input$sustable
values$datAll1[input$sustable+1,3] <- !values$datAll1[input$sustable+1,3]
})
As you might expect it changes the way i need it, but it triggers only on a value change - so if i click twice on the same item it would not fire the 2nd event.
How can i get the trigger on every click? Or maybe should i change the listener without passing the value to observer (if so, how? is there any Shiny.onInput without change?)

The solution i use for that is to add a second input, namely input$trigger, which i add to the javascript part. Assigning him a random number ensures that he fires on every click and triggers the code of the observer in the server function.
Shiny.onInputChange('sustable', sustable);
Shiny.onInputChange('trigger', Math.random());
and then let the server code listen on that:
observeEvent(input$trigger, {
values$datAll1[input$sustable+1,3] <- !values$datAll1[input$sustable+1,3]
})

I found the answer combining js script with shinyjs
i added onclick event to the gvis table that reads the listener and then changes the data
to the ui:
useShinyjs(),
extendShinyjs(text = jsCode),
and to the server:
onclick("sussimilar", {
values$datAll1[input$sustable+1,3] <- !values$datAll1[input$sustable+1,3]
})
of course BigDataScientist' answer is equally good as it calls for creating another entity just as mine
note: sussimilar here is the gVisTable name, not any particular function

Related

Oracle apex: adding filters programmatically with dynamic action adds duplicate filters

I have several dynamic actions that are fired with change event on page load. It seems like all of them are fired at same time. When that happens it adds filter to the interactive grid. Now, the problem is some of the filters are duplicated. How can I solve this problem?
I mean when page loads, it changes bunch of things in the form (like checkboxes and values of textfield), that fires the dynamic action, which then calls addFilter function like this
function newFilter(){
var vals = apex.item('P12_VALUE').getValue();
if(!(vals.includes('DI'))){
deleteExistingFilters('emp', 'IS_ON');
}
if(vals.includes('DI')){
if(!filterAlreadyExist('emp', 'IS_ON')){
addFilter('emp', 'IS_ON','Y','EQ');
}
}
}
Create only one dynamic action that fires on page load, but let it execute several ("true"?) actions, i.e. every action would be one or none of those "several" dynamic actions you have now. "None" means that you'd exclude it if it is already set.

Chrome DevTools listen to multiple selections of the same element in the elements panel

In my Google Chrome DevTools Extension I try to listen to the selections in the DevTools panel "Elements". In particular, it should be possible to listen to the selection of the already selected element.
My current implementation method revolves around the function chrome.devtools.panels.elements.onSelectionChanged. The function name already suggests that it is only possible to react to elements that are not currently selected.
Therefore I tried to reset or remove the current selection with the help variable $0, to be able to listen to the same element again - unfortunately without success.
My goal is to somehow listen to every click/selection in the elements panel. In summary, I am looking for an onSelection listener instead of an onSelectonChange listener.
EDIT #1
Here's my code I've tried:
chrome.devtools.panels.elements.createSidebarPane(
"Selector",
function(sidebar) {
// It fires if I'm selecting a specific DOM element via the elements panel the first time
// It won't fire if I'm selecting the same DOM element again
chrome.devtools.panels.elements.onSelectionChanged.addListener(() => {
chrome.devtools.inspectedWindow.eval(`(${getSelector})()`,
selector => {
console.log(selector)
// Here I tried to reset the current selection...
// I've already debugged it: I can assign a value to $0,
// but this implies that the value remains constant even
// after a new selection.
chrome.devtools.inspectedWindow.eval('$0 = undefined')
})
})
}
)
I am wondering if there is a way to change the selector programmatically...
I found a solution actually.
It looks like I overlooked the function inspect(<domElement>) in the Chrome DevTools documentation. With this function it is possible to programmatically change the auxiliary variable $0. I call inspect(document.body) at the end of each chrome.devtools.panels.elements.onSelectionChanged.addListener() function call, thus all other DOM elements become selectable again (several times).
Note: Ideally you should call inspect(<domElement>) on that DOM element where you know you don't want to select it multiple times.
I hope that I could help someone with the same problem.

HandsonTable - Modify DoubleClick Event

I am trying to modify the handsontable doubleclick event to have additional functionality. My current code is as follows:
hot.view.wt.update('onCellDblClick', function (row,cell) {
console.log("sucess");
});
This will sucessfully fire when a cell is double clicked on. However, it removes the current editing functionality of the cell.
Is there any way to update the on cell double click event whilst maintaining its current functionality?
Alright I ended up figuring this one out myself. So I thought I'd post the answer in the chance it helps anyone in the future.
hot.view.wt.update('onCellDblClick', function (row,cell) {
//Get editor and begin edit mode on current cell (maintain current double click functionality)
var activeEditor = hot.getActiveEditor();
activeEditor.beginEditing();
//Do whatever you want...
});
Thanks to the answer in the following post for defining how to manipulate the editor.
When using Handsontable how to force a selected cell into edit mode?

How can I overwrite a function in addEventListener?

In my application, there are several buttons which trigger my function loadObj(a). This function mainly loads the corresponding 3D object using the Three.js library.
When I choose a object and click the corresponding button, a set of three extra buttons appear which allow me to load three variations of the selected object. The code below already works for this scenario using addEventListener.
My problem arises when I select a different object, which triggers the code below again. Then, if I click one of the extra buttons for the newly selected object, it loads the correct object, but it also loads the previous one. If I choose a third object, if I click one of the extra buttons, it will not load just the corresponding object, but the previous two as well.
I have read that addEventListener works in a cumulative manner, where the functions just keep being added up. So, everytime it runs the loop below, it adds a new loadObj with the path of the new model to any other previous loadObj.
Is there any way to overwrite a function inside addEventListener? I need the previous loadObj to be removed from addEventListener before adding the new one.
//Solve the scope/closure problem to able to call loadDress inside the "for" loop below
function delegate(a) {
return function(){
loadObj(a)
}
}
for(var item in paths){
document.getElementById("size" + item).style.display = "inline-block";
document.getElementById("size" + item).addEventListener("click", delegate(paths[item]), false);
}
If you run that loop every time you click the button, it's adding an event listener on every run. That's why you keep getting more and more items each time--you keep adding more functions.
Instead of trying to dynamically add new event listeners on dynamically added buttons, you can delegate your event listening to a parent element that is a direct ancestor of all of the buttons. Then you have a single event listener that works for all of your buttons without any extra effort. You just check to make sure a click is from the right type of element and then you can get any relevant information directly from that element (via data- or other attributes on the event object target).

jQuery searchable checkbox list and tristate checkbox

I'm building a simple asp page on which I have list of peoples with checkbox on left of every name.
I've managed to create a simple jQuery script that allows hiding and showing rows of table based on input:
http://jsfiddle.net/Tq97v/ (first part)
As You can see I can enter part of name and then specific row are hidden.
Using red "x" I can uncheck all checkboxes.
What I'm trying to do now is to change that static red "x" into tristate checkbox.
Don't have idea how to even start.
Do I must add change listener to every checkbox in my list?
Second thing - how to create multiple instances of the same "plugin" on site.
Right now I'm identifying input by it, but it would be nice to call function with that input as param, and it would fine table after that input and create necessary logic.
This way I could call function multiple times on page to have more than one list.
I'm not asking for whole solution (of course it is always welcome :) ) but what I need is idea how to accomplish this in efficient way and as optimized as possible, because sometimes my list has 500+ elements.
P.S. don't look at HTML code, it is ASP generated.
I found this plugin: https://github.com/bcollins/jquery.tristate, but I have no idea how to use it with my list.
UPDATE:
I've managed to turn my code into functions, but right now I must call 3 functions for every list.
Here is my updated code: http://jsfiddle.net/65MEV/4/
How can I change it to one function? Will it be better?
This is my updated code. Still thinking about way of doing that Indeterminate Checkbox instead of my remove image.
UPDATE2
I build working code :)
http://jsfiddle.net/65MEV/9/
But I would like to improve it as much as possible.
Any suggestions are welcome!
A tristate checkbox is like the Three-Portal Device: an illusion.
What you actually want is to make the checkbox indeterminate (by setting the property of the same name to true). To implement this, you will need a change (or click) handler on each checkbox, then you'll need to check if all of them are in the same state, and if not then you set the indeterminate property. It's a hassle, really, because you rarely see indeterminate checkboxes and so most users don't know what to do with them. To be avoided, if possible.
To create multiple instances of the same plugin access elements relatively to an other element.
For example: in your case instead of keeping the item in a jQuery object var $tableRows = $('table.myList tr'); access them in the event.
$('#user_name').keyup(function () {
var sValue = $.trim($('input#user_name').val());
if(lastInput==sValue) return;
var $tableRows = $(this).next().next().find("table.myList tr");
if (sValue == '') {
$tableRows.show();
} else {
$tableRows.each(function () {
var oLabel = $(this).find('label');
if (oLabel.length > 0) {
if (oLabel.text().toLowerCase().indexOf(sValue.toLowerCase()) >= 0) {
$(this).show();
} else {
$(this).hide();
}
}
});
lastInput=sValue;
}
});
and you only have your actual list.
And for the tree state checkbox you don t need a plugin just add a button or link and every click check it status you can keep the status by jQuery data and change the element image according to this data.

Categories