Validation plugin hijacks click function? - javascript

Absolute newbie question, any help is highly appreciated :)
I am using curvycorners (http://www.curvycorners.net/) in combination with the jQuery validation plugin (http://bassistance.de/jquery-plugins/jquery-plugin-validation/), and I'm having problems getting the div to redraw the rounded corners when I do like this:
$("input[type='submit']").click(function(e) {
curvyCorners.redraw();
});
When I click the submit-button the first time the form validates, the validation error-message pops up and expands the div, causing the layout to go ugly. However when I click on it the second time the rounded corners redraw nicely.
Could it be that my validation plugin hijacks my initial click? How do I go about this? Any hint is very much appreciated.

Make sure that the handler you have above is set before the validation code is called. Event handlers are executed in the order they were bound, so if the validation plugin is cancelling the event, then you want to be attached before it does so.
In short, attach your handler first to make sure it gets executed and something else doesn't interfere.
Disclaimer: This isn't always true, something trying to interfere can (.unbind() for example) but it should solve your issue. If you see the same behavior after doing this, please provide more detail, something else is interfering.

Related

Trying to write a Fluid App userscript to disable notion sidebar auto popup behavior

Edit - working solution
Trying to disable the javascript event was a no-go, instead I ended up adding an additional element into the DOM that toggled the visibility of the sidebar with css which worked. It's not the prettiest solution as I'm just learning, but it does solve the problem.
It doesn't work as a Fluid userscript but does work as a Greasemonkey/Tampermonkey script in the browser. Full code is on Github - would love someone with more knowledge to improve on it.
Original Post
I'm a newbie in JS but am trying to learn by doing.
I use notion and am very annoyed by the sidebar that pops up whenever the mouse hovers over the left side of the app.
I read somewhere that I can use the Fluid app to push userscripts and that it might be possible to disable that functionality with custom styling.
But I can't seem to figure out how to get either the JS or CSS to disable mouseover events.
I think I found where the event is being listened for, but I'm not sure about next steps for how to remove that listener funtion, or to stop the function call.
This is where I think the event is being triggered, can anyone advise?
You can add a mousemove capturing listener to a container of the element with the listener. On mousemove, if the target (element to which the event is being dispatched) is a descendant of the element with the page listener you want not to fire, call stopPropagation on the event.
For example, in the below code, the page script tries to color an element when it or one of its descendants is hovered, but the second part (which can go into a userscript) will prevent that:
// Page script:
nested.addEventListener('mousemove', (e) => {
nested.style.color = 'red';
});
// Userscript:
outer.addEventListener('mousemove', (e) => {
if (e.target.closest('#nested')) {
e.stopPropagation();
}
}, true);
<div id="outer">
outer
<div id="nested">
nested
<div id="inner">
inner
</div>
</div>
</div>
So I wasn't able to solve this using the initial methods and ended up trying a totally different approach which worked.
Wasn't able to figure out how to get it to work in Fluid App yet, but I did manage a greasemonkey userscript.
Instead of trying to change the event listener function, I just control the visibility of the sidebar.
I add a button into the DOM, and give that button a trigger that toggles notions sidebar visibility. Click the button and the sidebar is invisible and nothing pops as you hover over the left side.
It's not the prettiest solution, because it doesn't remove notion's existing button for the sidebar, and if you don't minimize the sidebar with notion's own button, then the formatting can be a bit wonky, but as a hack it totally works.
I'm very new to JS and coding in general, so this is prob very inefficient. But if it helps anyone, here's the code in Github – I would love for someone to help me make this better.

Why is telling jQuery to click my link button slowing my page down?

I don't know if this is the effects of an update panel or what, but I basically have a drop down list that allows a user to select an item as a filter. When the item is selected it should bring back only one item into a grid view. That is this specific filter will at most bring back the record you are looking for. This works fine if the user clicks an "apply" link to apply the filter. Behind the apply link is some server-side code (C# within an ASP.NET Web Forms application).
We had a request by a user with something to the effect of:
"Why do I have to click the apply button if I make a selection in this
one drop down filter...it should simply get that one record I am
searching for. This helps me because I don't have to click the
"Apply" button."
I agreed with him and thought what is the easiest way to do this...I thought: Simple, I will have an on change event handler of the drop down such that when a selection is made I'll trigger a click event. Something to this effect:
$("#MainContent_ddlCompany").on("change", function() {
var companyId = $("#MainContent_ddlCompany").val();
$("#MainContent_hdnCompanyValue").val(companyId);
$("#<%=ddlCompany.ClientID %>").trigger("chosen:updated");
if (companyId.length > 0) {
$(".apply").click();
$(".apply").removeClass("applyButton");
$(".apply").addClass("resetButton");
} else {
//cleared selection of a company
$(".apply").removeClass("resetButton");
$(".apply").addClass("applyButton");
}
});
At first this didn't work, and I couldn't tell why, but then after some serious googling I changed this line:
$(".apply").click();
To this:
$('.apply')[0].click();
That worked great...so I decided to test it some more. As I kept selecting one filter value after another I noticed the page started to slow down. In fact by the 6th or 7th time it was pretty unusable. I don't know why it's happening, but I suspect again it has to do with the fact that this linkbutton with the class name .apply is inside an update panel.
But still I thought to myself, it was inside of an update panel before I changed my jQuery code to simulate the click event. So why does the page slow down and drag with this little piece of code? Is calling the event from jQuery code rendering something else in the HTML that could be causing this?
If I change my code back and force the user to click the apply button then we are back to a good normal speed. Why is it if I tell jQuery to simulate clicking the button my page slow down? It's doing the same thing, the simulation of the click of this link button is calling its server-side code method whether the user clicks it or I have jQuery click it.
For now I'm at a loss as to why this is happening because this button is in an update panel in either case, yet when I have jQuery click it via $('.apply')[0].click(); the page slows down after several attempts. Yet when I have the user simply click this button (without the jQuery click event) then it works fine?
What am I missing here?
Ugh, well, I found my issue. Because I was using updatepanels I had to wrap my jQuery code to include an add_endRequest. That is, you have something to the effect of:
$(document).ready(function() {
//Some initial event/triggers
var prm = Sys.WebForms.PageRequestManager.getInstance();
prm.add_endRequest(function () {
//Copy of some initial event/triggers
});
});
Why do I use the endRequest you ask? Well, because updatepanels basically throw away all your events after an asynchronous postback because the HTML at that point (after an update) is rendered again and at that point all events associated with any control inside an update panel are wiped away. At this point of course document.ready() does not run, so I have to resubscribe to these events inside of endRequest. Enter my issue...
I had a huge brain fart where I basically took everything, literally everything inside document ready and copied it into endRequest. In fact, if I remember correctly, I read articles which stated
Whatever you have in document ready simply copy paste into endRequest
That's fine, but you have to be careful here. I was throwing in events that were not wrapped around inside of an updatepanel into endRequest. The result is disastrous...at least for me.
These events would be attached then multiple times..or based on the number of asynchronous postbacks made. In my case, as I was testing I mentioned after the 6th or 7th time performance starts degrading. Well, by that time my controls were being attached that many times to events. For instance, my .apply button along with my dropdownlist were both outside of my updatepanel. But my jQuery code was attaching the change event of my dropdownlist in both document ready and endRequest.
The result is initially it's pretty fast, because it's only in document ready. But as I make asynchronous postbacks these events are being attached every time. For n tests I would have n attached events...in my case the test of 7 yields 7 on change event handlers!
Case in point, do not place any event handlers such as jQuery's on() event for any controls that are NOT inside an update panel. Otherwise you will run into what I ran into which was poor performance as events are happening.

is there an easy way to find code that is preventing event default?

This issue has come up for me a few times:
I write some code that handles an event, for example a click. I click the element and nothing happens. Some other code is calling e.preventDefault() before my code has the chance to handle it.
Question:
Is there a way to find the code that is preventing default that i have overlooked?
I usually solve this by running javascript profiler in firebug and looking at every function that is called during the click (not inside jquery etc) that may be doing the evil. There has to be a better way.
I would put a test alert in the function that is supposed to execute, starting at the top and then moving it downwards after each statement. If the alert doesn't execute at the top of the function I would check your HTML element and how you are selecting it. If everything appears to be good, I would search your files using possible element selectors.

How to write a smart onblur event

Lets imagine we have this sample code:
<input type="text" onblur="blurHandler()" />
<div class="results">
<ul>
<li>sampleText</li>
</ul>
</div>
Lets say you have currently focus on your input tag, and you hover to the "a" tag and click it. The browser will handle the onblur event first.
The task of the blur event is that it should hide the results div, but you still want to be able to click the link in the results div before that happens.
In blurHandler, use setTimeout() to delay hiding your div.
function blurHandler() {
setTimeout(function () {
//close the div
}, 100);
//do whatever else needs to be done
}
jsFiddle Demo
Another option would be to play with the mouseenter/mouseleave events on the link, and use a common flag between the event handlers so that they know about each other.
And one more: you can hide the div with a short animation, so it is actually still there when the click happens. Something like this:
$('.results').hide(1000);
jsFiddle Demo
Note: you should take a look at advanced event handling, inline event handlers can really mess up your HTML quickly. Separation of concerns helps others and your future self. If you use jQuery (seeing the tags under your question), you should use jQuery's event handling methods, which use the advanced model already.
I agree with Marcell's comment, though perhaps more from a usability perspective.
Assigning a timeout (as suggested by bažmegakapa) means you're choosing an arbitrary time limit that may or may not fire before the user has processed what they are supposed to do before that time limit is over. Unless your UI somehow makes it clear that they must react within a given time frame, this is likely to lead to frustrated users.
Even taking for granted that the users have had time to process the directions on screen, there's also transition time between moving from keyboard to mouse (or touch, where it's even worse as you have to deal with the UI shifting to hide the soft-keyboard), which means there's even more variance between different users' and their ability to follow the directions before the time limit you've chosen is over.
Just something to think about, in regard to how your interactivity is set up.

How to trigger a delayed jQuery event?

I'm writing a workaround for web form. The given problem is that hitting Submit pops out a loading animation. The content is saved, but the form is still shown, as is the loading animation.
The idea is to trigger an event, 2-3 seconds after the Submit click, that will reset the form content and hide the loading animation.
How would you suggest to approach this?
Thank you.
Use the callback functions in the events to chain them together - that way it will make sure that the action has completed, instead of trying to run all of them at the same time. If you post some code we can probably help some more. There's also the .delay() function, but I think callbacks are more appropriate, because your process is event driven and not time driven. You have more flexibility in the case that something in the process goes wrong, instead of statically resetting after a click.
Can you just use a setTimeout(...) that calls a method that resets form content and hides the animation? See: http://www.w3schools.com/js/js_timing.asp
jQuery Form came to the rescue.
$('form#id').ajaxForm(function() {
// do stuff
});
This will run the callback after the form is submitted.

Categories

Resources