How can I NOT trigger window.onhashchange on certain clicks? - javascript

I have 2 buttons, A and B. On clicking A the hashtag changes and I want to call the window.onhashchange function. But, on clicking B, I am manually appending a hashtag to the URL. In the later case, I don't want window.onhashchange to be triggered.

From your question I'm assuming you have generated HTML by PHP something along this:
<ul id='list-of-links'>
<li id='A'>Link A</li>
<li id='B'>Link B</li>
</ul>
Having that you wish that A does something else than B. In your JavaScript you can use the hash function.
var targetHash = window.location.hash.slice(1);
if( targetHash != 'posB' ) {
//do something as it's not 'posB'
};
Hope that helps.

Without any code all I can suggest is to check the id of the button that causes the event and act accordingly.

With little help of this answer and this one you can temporary remove event handles. Here's working example of jsfiddle.net with click event so assuming jQuery >= 1.8 it'll be similar, thus something like this:
// Initialization, add some events
$.hashchange(...);
// Store event handles for hashchange
hashchange_handles = [];
$.each( $._data($('#foo').get(0), "events")['hashchange'], function(i,handle){
// alert(handle.handler);
hashchange_handles.push(handle.handler);
});
// Remove handles
$.off('hashchange');
// Do your stuff here
// Restore event handler
length = hashchange_handles.length;
for(var i=0; i<length; i++) {
$.hashchange( hashchange_handles[i]);
}
It worked for click so hopefully it'll work for hashchange.
Note: I know the code is not perfect, you should tuned it. Plus I have tested it only for click.

Related

Unable to call .click function - Jquery

I'm creating a Firefox/Chrome Addon that goes on a 3rd party website. On this site, there is a list of about 512 names in one ul. I want to put 12 of them, based on their values and compared to an array.
Each li item looks like so:
<li><a class="manip" href="javascript:void(0);"></a><span class="draggable in-MultiCheckPossibleUserIdslistpair-possible ui-draggable"><a class="user" href="javascript:jQuery.wp.showModalWindow('/OneProof/User/Info/31654022')">Aaron Quinby</a><span class="id">31654022</span><span class="sortNo">1</span></span><span class="preview" style="display: none;">Aaron Quinby</span></li>
Right now, clicking on the a tag, with manip class will bring the li item from one ul to the correct ul. I want to do this automatically with my addon. I figured the quickest way would be to call the .click() event with jQuery on the a tag like so:
$(document).ready(function() {
$(".manip").each(function() {
//quick check to see if it works, click all
$(this).click();
});
});
I've played with the click, calling it in the console, calling it after a delay, and few other ways.
The only JavaScript I can find associated with the manip class in the source for this site is the following:
universe.find("a.manip")
.click(function() {
//alert("bound");
$.dropIt($(this).parent(), false);
});
Is there a reason why the .click call event isn't working?
Thanks!
Edit: Universe is defined here:
function listpairCore(options) {
var options = $.extend({}, $.fn.listPair.options, options);
var thisId = this.attr("id");
var ulSelected = this.find("ul.selected");
var ulPossible = this.find("ul.possible");
var universe = this;
and listpaircore is called here
$.fn.listPair = listpairCore;
The click function does not simulate a click. It binds an event handler to the click event.
What you want is
$(this).trigger( "click" );
Update:
The javascript you found in the source references the "manip" class as
universe.find("a.manip")
so maybe try doing the same?
$(document).ready(function() {
universe.find("a.manip").each(function() {
//quick check to see if it works, click all
$(this).trigger("click");
});
});

Javascript: addEventListener not taking updated DOM into account?

I'm very new to javascript and I'm trying to give some dynamic features to a site I'm working on. In particular, I want to have an unfolding menu item that unfolds and folds back whenever the mouse is on and off of it, respectively.
I got the unfolding part down but the event listener that triggers the folding back does it whenever the mouse if off of the area where the menu item used to be, event though it's just been extended.
The HTML markup looks like this:
<nav id="nav">
<ul>
<li id="elemPlaces"><ul id="drop"><li>Places</li></ul></li>
</ul>
</nav>
The event listeners are declared like this:
<script type="text/javascript">
var extended = false;
var listPlace = (<?php echo json_encode($list_place); ?>);
document.getElementById("elemPlaces").addEventListener("mouseover", extend);
document.getElementById("elemPlaces").addEventListener("mouseout", retract);
</script>
and the extend and retract functions are the following:
function extend()
{
if(!extended)
{
var drop = document.getElementById("drop");
var form = document.createElement("form");
form.setAttribute("action", "place.php");
form.setAttribute("method", "get");
drop.appendChild(form);
for(var i = 0; i < listPlace.length; i++)
{
var li = document.createElement("li");
var input = document.createElement("input");
li.setAttribute("class", "dropOption");
input.setAttribute("type", "submit");
input.setAttribute("name", "location");
input.setAttribute("value", listPlace[i]);
li.appendChild(input);
form.appendChild(li);
}
extended = true;
}
}
function retract()
{
var dropOption = document.getElementsByClassName("dropOption");
while(dropOption[0])
{
dropOption[0].parentNode.removeChild(dropOption[0]);
}
extended = false;
}
I realize it all must look amateurish but like I said, I'm new to this. I'd really appreciate it if someone could help me.
Okay JSFiddle seems to be down, so here is a Plunker
Basically :
Use mouseenter and mouseleave (see this question)
I believe in your case you just want to redirect to a page passing a GET option. You can do it using <a href="yourpage.php?yourOption=yourValue">. It is simpler. You don't need forms for this.
As I said, here it's a bad idea to modify the dom. Or well, it depends on where your list comes from. If your $list_place comes from an AJAX asynchronous request, then obviously you can't do anything else but modify the DOM dynamically. However if you know beforehand what the content of your list will be, best it to just write everything to the HTML, and add classes like class="unexpanded/expanded", and have a CSS .unexpanded{display: none}. Then you just need to toggle/change the class
So basically what you want to so, is make sure the menu stays unfolded a certain amount of time before folding back ? Here are some ideas
Instead of calling retract on mouseout, you could call another function with a timeout, like retract_after
function retract_after(){
setTimeout(function(){ retract() }, 3000);
}
But this could lead to weird situations (imagine the user moves the mouse on the menu just after moving it out, before the timeout expired...). So you might want to lookup how to empty the queue or remove EventListeners.
Or, what you could do, is only attach the "retract" eventListener at the end of the mouseover function (and also eventually with a timeout), and remove the eventlistener while or after it is retracting.
Also the animate() function of jquery library already somewhat produces by default the behavior you're looking (it queues animation, but if a user quickly triggers mouseenter and mouseout event listeners, the menu will keep folding/unfolding till it empties the queue)

How to fire a double-click on click()

I am working with jaccordian and am wondering how JavaScript can fire a dblclick() when the user fires a single click. The trick is that it should only happen on specific classes.
One can use https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.dispatchEvent in most moddern browsers or just call .trigger - http://api.jquery.com/trigger/ in case you are using jQuery.
i cannot know exactly what you want BUT
if you want the double click to be on a different selector then you can simply do this
$('.your_selector').click(function() {
$('.another_seletor').dblclick();
});
while if you want to fire the double click to the same selector then i you just cal $('selector').click() inside you $('selector').click(function())
here:
$('foo').click(function() {
$('foo').click();
});
finally (i hope this is what you want), the pseudo code is like this:
$(many_selectors).click {
//do a lot of code
//but
if(class of clicked element is foo)
do a double click
}
this case it is the same like the second example but you only need to add the following:
var cls_of_elems_w_dbclk = ['class1','class2','class3'];
var class_of_clicked = $(this).attr("class");
if ($.inArray(class_of_clicked, cls_of_elems_w_dbclk) !== -1) {
//then perform a another click
$(this).click();
}

How to handle an indefinite number of events?

So say I have some code that creates an indefinite number of comments in a main section of the page, such as
function createcomments(comments) {
var main = document.getElementById("main");
for (var i = 0; i < comments.length; i++) {
var comment = document.createElement("quoteblock");
comment.innerHTML = comments[i];
main.appendChild(comment);
comment.classList.add("comment");
}
}
And every time a visitor to my page hovered over a comment the background would turn red or something:
window.onload = function() {
var comments = document.querySelectorAll(".comment");
// code for handling .onmouseover and .onmouseout
// for each element in the array
}
How would I do that? I think there is a way to do it with jQuery, but I was wondering if there's a way to do it with JavaScript.
In jQuery there are this two helper functions delegate() and live().
They work as nicely described in this blog post.
Actually you can attach an eventHandler to a parent element that is than listeing to all mouse events (and other events). Using delegation you then check on the parent elements eventHandler if the event is coming from a specific child.
<ul>
<li>one</li>
<li>two</li>
<li>three</li>
</ul>
here we add some simple html, but we dont attach to the span element for a click handler, but to the div. in the div eventHandler we then check, what target actually got clicked
var divs = document.querySelector("ul");
divs.addEventListener("click", function(ev) {
if (ev.target.tagName === "LI")
console.log("A list element (" + ev.target.innerText + ") was clicked");
});
The whole reason behind this delegation is performance. also, if you remove or add items dynamically, the event handling works as expected without any additional work.
If you dont want to use the whole jQuery for this simple step, I still suggest you use some framework, as it is always better to use community support than reinventing the wheel
try http://craig.is/riding/gators, looks nice :)

How defined in jQuery was it a regular click on the same element or double-click?

How can I define in jQuery was it a regular click on the same element or double-click?
For example we have element like this:
<div id="here">Click me once or twice</div>
And we need to perform different actions after regular click and double-click.
I tried something like this:
$("#here").dblclick(function(){
alert('Double click');
});
$("#here").click(function(){
alert('Click');
});
But, of course, it doesn't work, everytime works only 'click'.
Then, some people showed me this:
var clickCounter = new Array();
$('#here').click(function () {
clickCounter.push('true');
setTimeout('clickCounter.pop()', 50);
if (clickCounter.length > 2) {
//double click
clickCounter = new Array(); //drop array
} else {
//click
clickCounter = new Array(); //drop array !bug ovethere
}
});
Here we tried to set the interval between clicks, and then keep track of two consecutive events, but this have one problem.. it doesn't work too.
So, someone knows how to do this? or can someone share a link to the material, where I can read about it?
From QuirksMode:
Dblclick
The dblclick event is rarely used. Even when you use it, you should be
sure never to register both an onclick and an ondblclick event handler
on the same HTML element. Finding out what the user has actually done
is nearly impossible if you register both.
After all, when the user double–clicks on an element one click event
takes place before the dblclick. Besides, in Netscape the second click
event is also separately handled before the dblclick. Finally, alerts
are dangerous here, too.
So keep your clicks and dblclicks well separated to avoid
complications.
(emphasis mine)
What you are doing in your question, is exactly how it should be done.
$(".test").click(function() {
$("body").append("you clicked me<br />");
});
$(".test").dblclick(function() {
$("body").append("you doubleclicked me<br />");
});
It works and here is an demo for that.
Since, you want to detect separate single double click. There is a git project for this.
$("button").single_double_click(function () {
alert("Try double-clicking me!")
}, function () {
alert("Double click detected, I'm hiding")
$(this).hide()
})
It adds up events to detect single double clicks.
Hope it helps you now.

Categories