Materialcss modal not working with datatables.js - datatables

I am trying to build an admin dashboard using material design framework. As a part of it, I am trying to add modal-trigger element inside a <td></td> tag of a table that uses datatable.js library. But when I click on the trigger no modal is appearing. Did anyone face similar issue before?

I think that what's happening is that your trigger isn't in the DOM when you draw the table, but without seeing your code I can't be sure. Generally, it will trigger a modal when it is clicked or something? You might want to change the actual triggering to clicking on a td with a given class contained within the table so something like this:
$(".modal-trigger").click(function(){//Open Modal});
This would work on the first page but not after the first draw of the table as the event had been registered before the elements were within the DOM. Rather, you'd need to listen to the click within the table like this:
$("#table-id").on("click", ".modal-trigger", function(){//Open Modal});
I hope that makes sense and that it helps, if not perhaps work up a JSFiddle illustrating your issue?

Related

Drag and drop two elements and execute POST call with InteractJS and Htmx

Disclaimer: This is more an architectual question.
I am trying to build a quite simple UI. I have two lists of elements, all elements in boths lists are of the same type. If I drag one element from the left to the right onto an element of this list, I want to execute a POST call to the backend sending both data-obj-id attribute values along.
I settled on InteractJS and HTMX but its f**** hard to build something like this.
My approach: I need to fire some kind of event to trigger the HTMX POST call. But the event needs to know which elements are being dropped on each other. So I need a custom event (not possible to get the drop event anyway), which contains the ID of the other element.
I tried:
const newEvent = new Event('interactjs:drop-'+draggableElement.getAttribute('data-obj-id'));
document.body.dispatchEvent(newEvent);
<div data-obj-id="{{ my_obj.id }}"
hx-post="/my-post-call"
hx-trigger="interactjs:drop-{{ my_obj.id }} from:body">...</div>
But the moment the event contains a number, it's not recognised anymore. I guess I just chose a poor choice of architecture to solve my problem?
Thx!

How can I change the styleClass of a control while also doing a partial refresh on another component?

I have a straightforward XPage that lets a user answer a question with a simple Yes/No/NA response using radio buttons. I have restyled the radio buttons to look like a bootstrap button group to make it visually more interesting for the user. If the user chooses "Fail" then they are informed that they need to do something else - easily done with a simple partial refresh to a div further down the page.
This all works fine.
The problem I'm having is that I'd like it so that when the user selects an option, I would like to add a new class of "active" to the selected option so that it highlights in a pretty colour. But for the life of me I can't get this to work and though I'm sure it's a straight forward problem, I can no longer see the wood for the trees.
My current (abridged) iteration of the radio button code is this:
<xp:div styleClass="btn-group item-result" id="edit-result" loaded="${Question.open}">
<xp:radio text="${lbl.kwPass1}" id="itemPass"
styleClass="btn btn-pass #{(item.itemResult eq '0')?'active':''}" groupName="itemResult"
selectedValue="1">
<xp:eventHandler event="onchange" submit="true"
refreshMode="partial" refreshId="actionAlert">
<xp:this.script><![CDATA[XSP.partialRefreshPost('#{id:edit-result}');]]></xp:this.script>
</xp:eventHandler>
</xp:radio>
<!-- other radio buttons -->
</xp:div>
<!-- other page compenents -->
<xp:panel id="actionAlert">
<!-- panel content and appropriate rendered value -->
</xp:panel>
This was attempting to do a chained partial refresh on the radio button container so that the EL would evaluate and apply/remove the 'active' style based on the document datasource ('item') value. I have also tried using dojo.addClass, dojo.removeClass, XSP.partialRefreshGet and other options. I don't mind what the solution is as long as it's efficient and works. I'd prefer not to move the actionAlert panel to within the same container as the radio buttons and I can't do a full page refresh because there are other fields which will lose their values.
Some notes:
I'm not using a RadioGroup control because it outputs a table and I haven't got around to writing my own renderer for it yet. Single Radio button controls work fine for what I need them to do.
I originally tried using the full Bootstrap solution of using "data-toggle='buttons'" (source) which sorts out applying the "active" style fine but then, inevitably, prevents the partial refresh from working.
the radio button styles are clearly not Bootstrap standard
Any assistance pointers or, preferably, working solutions would be appreciated.
You need to aim your partial refresh at the div containing all your radio buttons. Give it an id, so you can address it.
Partial refresh, as the name implies, refreshes one element and its content only. So you target the element that covers all of the items you need to recompute.
Stepping away from the problem, a couple of beers and an episode of iZombie later, I realized what I was doing wrong and sorted it out. So, for posterity, here is the simple solution that I swear I tried earlier but clearly works now:
<xp:div styleClass="btn-group item-result" id="edit-result" loaded="${Question.open}">
<xp:radio text="${lbl.kwPass1}" id="itemPass" value="#{item.ItemResult}"
styleClass="btn btn-pass" groupName="itemResult" selectedValue="1">
<xp:eventHandler event="onchange" submit="true" refreshMode="partial" refreshId="actionAlert">
<xp:this.script><![CDATA[dojo.query('.item-result > .btn').removeClass('active');
dojo.query('.btn-pass').addClass('active');]]></xp:this.script>
</xp:eventHandler>
</xp:radio>
<!-- et cetera -->
The many places I was going wrong:
In my code in the question, I was calling XSP.partialRefreshPost in the CSJS script of the radio button when it should have been in the onComplete of the eventHandler. It has to be chained to another partial refresh so that it runs after it, not at the same time. I did end up getting this right - but overlooked something I'll come to in point 3.
In my original attempt to use Dojo, my first mistake was to try and target the ID of the radio button, something like:
dojo.addClass(dojo.byId('#{id:radio2}'),'active');
This actually works as expected, so long as you remember that the ID of the radio button on the XPage refers to the actual radio button control and not the label wrapping; and the label is what I wanted to style. So the class "active" was being actually being added, just not to the element I thought it was. I should have spotted this in my browser code inspector except for the third thing I got wrong:
Ironically, I sorted out the first issue, remembering to put the XSP.partialRefreshPost into the onComplete - and then didn't remove it when trying to run the Dojo.addClass(). So I didn't notice the mistake with the addClass targeting the wrong element because after it ran, the partial refresh updated the container and removed the class I had just added which made me think that nothing was working.
So now I have some neatly styled radio buttons that don't look like radio buttons and it's all managed client side without any unnecessary partial refresh trips to the server barring the one where I actually need to look stuff up from the server. And the vital lesson is - sometimes you just need to step away from a problem and come back to it with fresh eyes later on.

Get the current slide element on change event in OwlCarousel2

I am trying to create an effect similar to this (the demo uses Bootstrap Carousel):
https://codepen.io/SitePoint/pen/BpVrXP/
Bootstrap's 'slide.bs.carousel' returns a relatedTarget that is the slide element going to be displayed as soon as the carousel is moved i.e changed to another slide.
I haven't been able to find an equivalent data being returned in OwlCarousel2's changed.owl.carousel event. What event, if any, returns the element that's going to be in view?
Is there any alternative way or am I missing something?
Try the event translated.owl.carousel, translated is fired after the animation

Seaside calling a component inside javascript

I have a seaside application with a master-detail page. The master page has a table that consists of a list of tr records. When the user clicks a particular tr element, I want to call a detail component, which'll show the individual record's data.
Since I cannot make a tr element with callback or have it contain an anchor with a callback, I want the tr's onClick property to have some JavaScript which'll call: subcomponent . When I tried this, I got an error saying call: can only be used in callbacks and tasks.
Using ajax is a workaround, however it breaks the back button.
Edit:
More generally, I'd like to know how to set callback like behaviour for various JavaScript events.
Well, you cannot render a component in a tr element, but you could add some anchor or other element in one of its td children.
For my project I did roughly the following: I added an anchor to each row with a special css class, e.g. '.dblclick-action'. This anchor has a normal Seaside callback.
Then I bound a dblclick handler to the tr element that does something like document.location=$(this).find('.dblclick.ction').get(0).href;
I am not close to a Smalltalk image now to give you source code, but I hope you get the idea: you don't use Ajax to click the link in that particular row, but instead have the browser navigate to the callback that is associated to the link in that row. You could say you use the tr.'s dblclick handler to click the link and then let the normal Seaside stuff do its work. No magic there. You can find a little bit more info here.
If you don't want the anchor to be visible you may want to experiment with making the anchor invisible (display: none) or the like.
If you are a bit more experiment friendly, you can also try saving a callback on the server and render its url with callback id as an attribute of the tr element and use the dblclick handler to follow the link from that attribute you extract the value of an attribute in query using attr().
I forgot to answer your initial question: you cannot issue a call: from javascript. But you can use the document.location trick to re/misuse an existing link to a callback on the page using the technique I described in my first answer.

Dojox.grid.DataGrid - in a widget - only renders on visible tab

I am using a Widget that contains a DataGrid object. The Widget works fine when included in the first tab (this is the visible tab), but not when I use the same code on a second tab.
The code is the same I have done several checks to make sure there are no other problems - and non Grid code is rendering fine - only the grid that has a problem. I have tried setting the height and width manually and this just results in a large grey rectangle on the second tab.
Do I need to tell the Grid to refresh in some way - or is it a property for the TabContainer?
Help - this is driving me mad!
Yeah, that's a big problem with the grid. If you use it declaritively in a tab container, it won't render properly on the non-visible tabs. It needs to calculate height/width (even though you specify them)...as you have seen.
The way I got around it was to create the grids programatically on tab select. I posted about my solution on the dojo forums. My code sample is over on github. It's a bit too large to post here methinks. Let me know if you want it, and i'll edit my answer.
There's also a discussion on nabble with a different solution.
"resize" works like a charm! Been looking for this for a long time (didn't know what I had to search for), thanks.
I use this routine to dynamically determine if the tab has more than one datagrid, as I may not know the ID of one single grid, maybe someone else might use that, too:
dojo.query('div#container div[id^="gridNode_"]').forEach(function(node, index, arr) {
dijit.byId(node.id).resize();
});
This will check the div with id="container" (skip that part if you want to search the whole DOM) for divs with an id starting with "gridNode_" and apply "resize" to those widgets.
An alternate approach is to resize the grid upon tab element selection. Sample code
dojo.connect(dijit.byId('my_tab_container'), "selectChild", function(child){
// if second tab (could be any...) selected
if(child.id == 'mySecondTabId'){
var myGrid = dijit.byId('myGridInsideTabId');
if(myGrid != null) myGrid.resize();
}
});