Is it possible to use browser->drag() from dusk with Vuedraggable? - vue.js

We are using VueDraggable (and Vue) in our front-end and we are testing our front-end with Dusk.
I am currently trying to use $browser->drag('selector', 'selector') from dusk to drag objects from one list to the other, but I don't see anything happening during the test (although it might be the action is not visible) nor is the right result shown, the object does not end up in the indicated list.
I was wondering if anybody made a working example already of using $browser->drag() combined with Vue.draggable? I am asking since I don't know if I am trying the impossible or not.

There is an open issue for this on Dusk's Github. I had to open a new issue that can be found here since the original was closed for comment. The link contains a more thorough explanation, but the short answer and solution are highlighted here:
Problem: Laravel's Dusk does not trigger Vue.draggable events. To simulate a drag-and-drop Dusk does a "mouse down", "move mouse to location", and "mouse up" sequence. In theory this is correct but does not trigger Vue' s events.
Solution: Dusk's method does trigger mouse down and mouse up events, so we can simply use those events to trigger the ones desired.
$("a[draggable='true']").on("mousedown", function(event) {
$(this).trigger("dragstart");
});
$("div[droppable='true']").on("mouseup", function(event) {
$(this).trigger("drop");
});
This JSFiddle is an example of how it would work (though you need to implement it on a Laravel project to truly test, of course!).

Related

Bootstrap tooltip not showing in ASP.Net MVC application

I've got a rather weird scenario going on here. I am trying to add tooltips to an existing ASP.Net MVC application in which I'm upgrading Bootstrap to 4.6.2. The upgrade was very smooth with no complications; I just want to replace the default display of titles with the nicer looking tooltips, but for some reason they're not appearing. I tried to simplify things by creating a new view to isolate the problem, and still no tooltip. I tried again with completely new solution, and wouldn't you know it, it works! So my question isn't "how do I create tooltips", but "how can I debug what's going on in the failing project?"
Here's what I've discovered so far. I believe you can see everything that's relevant in this screenshot of the nearly-empty view. All the included script files are there in the right order, my script is there, initializing the tooltip, and there are no messages in the console. When I hover over the link, a new <div> element is added to the DOM. In DevTools, I use the arrows to expand the tree, showing everything in the tooltip. The .fade:not(.show) CSS selector is the reason I don't see it. In the working solution, the show class is properly added to the tooltip's <div>.
So, could there be some setting in the existing application preventing the addition of the show class? Is something failing in the tooltip code,causing it to never add the show class without reporting errors? How should I continue debugging this? I tried stepping through the bootstap.js file, but being a JS noob, I'm getting a little lost. The screenshot is from Chrome, but I see the same behavior in Firefox.
This turned out to be one of those embarrassing oversights. My BundleConfig.cs file was still pointing to old Javascript files that were still hanging around after the upgrade. I should have seen it in the version numbers in the <script> tags.

Cycle.js/xstream click event streamed once, but fired twice

There's a single button element on the page and the following click stream:
let submitClick$ = sources.DOM.select(buttonSel)
.events("click")
.mapTo(true)
.debug(console.log)
Once I click on the button, true is logged, which is correct.
However, when I map the stream, the code inside runs twice:
let submitDeal$ = submitClick$.map(() => {
console.log("Clicked")
// ...
})
No other event handlers should be attached to the button, and the element itself sits inside a div:
button(".btn--add", "Submit")
The usual event.preventDefault() and event.stopPropagation() doesn't make a difference, and inspecting the event does show that it is fired from the same element button.btn--add.
Not really sure what's going on, any ideas are appreciated! Thanks!
Versions:
"#cycle/dom": "^12.2.5"
"#cycle/http": "^11.0.1"
"#cycle/xstream-run": "^3.1.0"
"xstream": "^6.4.0"
Update 1: I triple checked and no JS files are loaded twice. I'm using Webpack that bundles a single app.js file that's loaded on the page (Elixir/Phoenix app). Also when inspecting the button in the Event Listeners tab in Chrome's Developer Tools, it seems that only 1 event handled is attached.
Update 2: Gist with the code
Too little information is given to resolve this problem. However some things come to mind:
You shouldn't use .debug(console.log) but .debug(x => console.log(x)) instead. In fact .debug() is enough, it will use console.log internally.
Then, is the button inside a <form>? That may be affecting the events. In general this question needs more details.
Turns out this was due to a bug in xstream, which was fixed in xstream#7.0.0.

safari OSX voiceover not reading aria label for input

I'm trying to get voiceover to work on safari however, it seems when I tab through elements it doesnt read out the aria-label of the new input box in a certain scenario.
Scenario:
When tabbing onto the next element and the on blur of the current element does something to the dom then it will not read out the aria-label of the next element.
Here is an example
http://plnkr.co/edit/x0c67oIl0wlQEguBIQVZ?p=preview
Notice if you take out the onblur function below then it works fine.
<input id="test" onblur="blurer()" onfocus="focuser()"/>
In this case, the issue isn't the presence of a blurer, but rather the contents of your blurer and corresponding focuser functions. Together these two functions are toggling the hidden state of a nearbye element. This is interupting the announcement. There's a role announcement that also occurs. The full annoucement (when text is populated in the edit text control) should be:
"The edited text" contents selected/unselected, "your aria label", edit text.
The quoted portions are parts you control, the other portions are parts controlled by the OS/VoiceOver's interaction with it, calculated automatically by the state of the control and other aria values.
The announcement we're getting is simply
"The edited text"
So, it's not an issue with the aria-label specifically. But rather, you are causing the entire announcement of the element to be interrupted.
When your blur and focus functions trigger you muck with the VoiceOver's response (or the OS's communication of) these events. Not sure what about your functions is causing this. Regardless, a trick that helps in these circumstances is to add a setTimeout to your code. By separating your function and the actual focus/blur event, you can allow the accessibility APIs to do their thing, before mucking with styles and such on the page. Here is an example that makes your little code snippet work. Just replace the contents of your javascript file with this:
function blurer(){
window.setTimeout(function() {
document.getElementById('myDiv').style.display = 'none';//
}, 0);
}
function focuser(){
window.setTimeout(function() {
document.getElementById('myDiv').style.display = 'block';//
}, 0);
}
In general I like to avoid setTimeouts because they create race conditions. However, setTimeouts of 0 are acceptable, because there is no race condition. You're just decoupling the firing event and the execution of your code by pushing your code to the end of the queue. When hacking around VoiceOver, setTimeout(someFunction, 0) works quite well for a lot of cases.

Dojo 1.4.2 Tree Grid "expando click" event? persist state?

Question:
Given a DOJO TreeGrid, how can I capture the event when a user clicks the expando ("+") button to expand a row, and store the specific row number or associated item's identifier? I'd like to do this for the express purpose of completely deleting the TreeGrid from the DOM, rebuilding it, and restoring it's state once rebuilt (i.e. programmatically expanding the rows that the user has previously expanded).
Background:
So I've got a custom DOJO TreeGrid, hooked up to a custom QueryReadStore, in my app. It was constructed using the following tutorial:
http://www.ibm.com/developerworks/web/library/wa-dojotreegrid/index.html?ca=drs-
Pretty interesting tutorial, but it might be irrelevant to my question because it doesn't really squash any functionality, it only seems to augment it.
Anyway, googling around for a moment, I found a nice function in the DOJO forums that I can use to programmatically expand a row, given the specific row index. Works perfectly.
The problem is that I haven't been able to find a good way to capture the expando click event, and relate it to a specific "parent item row" index in the grid.
Details aside, I'd like to get the row index of every row that the user has expanded, into an array (and delete the index of a row that the user collapses, obviously), so I can destroy this TreeGrid, and faithfully rebuild it, with the user's selections expanded properly.
I'm not really a novice to DOJO, but I'm certainly no expert by any means. I've done a fair bit of googling, and FireBugging, and haven't really been able to find anything that I can use to do this.
Suggestions? Anybody done something similar before? Stupid question with obvious answer that I've missed? I'm totally misguided and am going about it all wrong? Thanks everybody!
Something similar to this would probably work, this is how the dijit.Tree implementation wouldve looked;
var expandedNodes = {}
dijit.tree._onExpandoClick = function (args /* object wrap for args.node */) {
var treeNode = args.node,
path = treeNode.getTreePath(),
id = treeNode.getIdentity();
expandedNodes[id] = path;
}
I am not 100% sure im being strictly correct but for the TreeGrid you will have to look through code of dojox/grid/_TreeView.js (link). The _setOpen would be an entrypoint from which you can 'hook' the onclick action. from there, find the expandoCell.openStates hash, this is a true/false variable set, indexed by itemId. This hash is most likely what you need as your state

Using Dojo to reenable a submit button when a form is edited

I'm trying to build a web app using Dojo. I have a form that posts data via Dojo's xhrPost capabilities to a server side program that saves changes made on the form whenever the user hits the "save" button. What I would like to do is disable the save button after a successful save until the next time something is changed in any of the form's fields to avoid repeated attempts to save an unchanged document.
I tried having Dojo's event watching functionality watch for changes, but have not been successful. The event intended to trigger reenabling the save button never does anything. Here is what I tried:
eventWatching.push(dojo.connect(dijit.byId('editForm'), 'onChange', function() { dijit.byId('saveButton').set('disabled', false); }));
Using onKeyPress instead of onChange seemed promising, but that did not (obviously) reenable the button when the form was edited using the mouse alone.
Prior to 1.6, I don't think dijit.form.Form connects its children's onChange to its own, which is likely why your onChange idea didn't work.
In Dojo 1.6, what you're asking for is easily possible by taking advantage of the fact that widgets now inherit dojo.Stateful functionality:
form.watch('value', function(property, oldvalue, newvalue) {
/* ... */
});
In 1.5 or lower this might take some work; can't think of an easy way off the top of my head but maybe someone else has an idea or one will hit me later.
You can find the code responsible for hooking up the onChange and value-watching functionality in 1.6 here: https://github.com/dojo/dijit/blob/master/form/_FormMixin.js#L396-429
If the newvalue is emptyString the form is valid.
frm1.watch('state',function(property, oldvalue, newvalue) {
console.log(newvalue)
})