In this project am working on I have button that has and image inside it for styling purposes... I am trying to implement the functionality such that when the button is clicked I use event.target.parentNode.parentNode... a number of times to get an HTML5 data attribute(postid) from one the topmost parent divs, in Firefox I need to call parentNode 4 times and it works in Chrome it does not work I need to call parentNode 5 times, this means the two browsers are referring to different parents. I added $(event.target).parent().parent().css('border','5px solid black'); to find out which target each browser is considering. I found Chrome considers the event.target to be the image(which is what is actually clicked) but Firefox considers the button to be the event.target(which is where the event was actually attached)..... How can I make this button and its event code portable on both browsers without removing the image inside the button tag(that worked).
The code looks like
$(document).on('click', '.opinion', function(event) {
try {
post_id = event.target.parentNode.parentNode.parentNode.parentNode.dataset['postid'];
//$(event.target).parent().parent().css('border','5px solid black');
url = $('#opinionUrl' + post_id).val();
token = $('#token').val();
} catch (e) {
alert(e);
}
///Some more code to do stuff
});
<button class="icon opinion">
<img class="icon" src="{{URL::asset('assets/icons/haha.png')}}">
</button>
Why use jQuery and chain parentNode or .parent()?
.closest() will do the job for you https://api.jquery.com/closest/
post_id = $(this).closest("[data-postid]").data().postid;
Related
Hello I'm trying to use the html drag and drop feature with jquery. I generate my draggable (a button) like this
$("#tb > tbody > tr").append(($("<td>")).append($("<input/>", {type:"button", id:"bt", draggable:"true", value:"test", class:"bt-test"}))).append($("</td>"));
So far, and after reading a bit on the subject, I'm trying to deal with the different events like this :
$(document).on("dragstart", ".bt-test", function(evt)
{
evt.originalEvent.dataTransfer.setData("text", $(this).val());
alert(evt.originalEvent.dataTransfer.getData("text"));
evt.originalEvent.preventDefault();
});
$(document).on('dragenter', function(evt){evt.originalEvent.preventDefault();});
$(document).on('dragleave', function(evt){evt.originalEvent.preventDefault();});
$(document).on('dragover', function(evt){evt.originalEvent.preventDefault();});
// still irrelevant at this point
$(document).on("drop", ".btCase", function(evt)
{
var data = evt.originalEvent.dataTransfer.getData("text");
$(this).val(data);
event.originalEvent.preventDefault();
});
The alert within the dragstart listener shows up just fine on chrome but it doesn't on firefox.
I already tried adding an ondragstart="dragstart_handler(event);" directly into my button as mentionned in https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API but the problem remains. I also tried replacing the event.originalEvent.preventDefault(); with return false();
Any tips?
edit : fiddle > http://jsfiddle.net/Nn4x2/4/
This works with a div element, see http://jsfiddle.net/Nn4x2/26/
It seems draggable input buttons are not supported in Firefox. It may be best to use a styled anchor element instead.
This is logged as a Firefox bug for button elements - see https://bugzilla.mozilla.org/show_bug.cgi?id=568313
I'm trying to change the text of the link when it's clicked and show a DIV. After the user clicks on the modified link (same one) it should hide the DIV.
It works with showing it, but for some reason when I click "Hide older news" the DIV is hidden for like half a second and then it shows again.
It happens on the line where I'm changing the link's text to the default one ("View older news...")
<script>function showoldnews()
{
document.getElementById('oldnews').style.display = "block";
document.getElementById('oldnewslinkid').innerHTML = 'Hide older news';
}
function hideoldnews()
{
document.getElementById('oldnewslinkid').innerHTML = 'View older news...'; //it calls showoldnews() function for some reason on this line
document.getElementById('oldnews').style.display = "none";
}
</script>
Link
View older news...
I believe this is happening because you are inserting a second link inside your first link, and the click event is firing for the parent anchor, instead of the child.
Your markup:
<a href="#" id="oldnewslinkid" onclick="showoldnews(); return false;">
Hide older news
</a>
There are several ways around this:
Wrap your controls in a containing div, and append a new anchor to its innerHTML
Include both sets of controls in the dom on load, hide your hideOldNews() control via css, and toggle them via js
Attach an event listener to one element, and use it to "toggle" your news div:
HTML
<div id="oldnews">Old News...</div>
View older news...
JS
var toggle = document.getElementById('toggle')
toggle.addEventListener('click', function(e){
e.preventDefault()
var target = document.getElementById("oldnews"); // href="oldnews"
console.log(target);
target.style.display = (target.style.display == 'none') ? 'block' : 'none';
});
codepen
My suggestion would be to use an event handler, it will make your life a lot simpler, as you are not having to edit single line JS nested inside ofHTML elements.
There are are some slight cross browser issues with addEventListener (IE8 uses a special attachEvent handler), bit there are some simple ways to get around that.
I was trying to use querySelector to find active elements in a page. I assumed that a handler bound to a mousedown event on the document would trigger after the event had bubbled its way back from the target, which means the :active pseudoclass should already be applied.
document.addEventListener("mousedown",function(e){
console.log(document.querySelector("*:active"));// logs null
// expected value was the target of the mousedown event, that is,
console.log(e.target);
});
My question is: at what point exactly does the the :active pseudo-class apply? Note that when I log the value, the mousedown event has already triggered on the target.
See http://jsfiddle.net/tK67w/2/ for an example. An interesting thing to note here is that if you set a breakpoint within the handler, you can see the css rule I defined for a:active already applying, although querySelector is returning null
EDIT:
Credit goes to TJ for coming up with a much better demonstration. The problem still stands though: in browsers other than IE and Chrome, how can I get an HTMLCollection of all active elements as they become active?
I believe the issue is that as you're using querySelector, you're only getting the first active element. But your anchor is much further down the tree.
Update: Interesting, I'm not getting anything with Firefox or Opera, but I am with Chrome. The below are Chrome results. See more on that below.
Consider (live copy):
document.addEventListener("mousedown", handler, false);
function handler(e){
console.log(
"event " + e.type + ": " +
Array.prototype.join.call(document.querySelectorAll("*:active")));
}
When I click the anchor, I see this in the console:
event mousedown: [object HTMLHtmlElement],[object HTMLBodyElement],[object HTMLDivElement],http://fiddle.jshell.net/_display/#
Note the URL at the end, which is the default toString for HTMLAnchroElement instances, which is triggered by the join.
Since querySelectorAll is required to return the elements in document order, if you want the most specific active element, you'd use the last one. Example (live copy):
(function() {
document.addEventListener("mousedown",handler, false);
function handler(e){
var active = document.querySelectorAll("*:active");
var specific = active && active.length && active[active.length-1];
display("Most specific active element: " +
(specific ? specific.tagName : "(none)"));
}
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
})();
In my case (using Chrome), I see the tag name of the most specific element (the anchor if I click the link, etc.).
It seems like Chrome is following the spec and taht Firefox and Opera are not. From Section 6.6.1.2 of the CSS3 Selectors spec:
The :active pseudo-class applies while an element is being activated by the user. For example, between the times the user presses the mouse button and releases it.
It seems to me that :active should therefore apply in the above. This assertion is backed up if we use this CSS:
*:active {
background-color: red;
}
...with this JavaScript:
(function() {
document.addEventListener("mousedown", mouseDown, false);
document.addEventListener("mouseup", mouseUp, false);
function mouseDown(){
var active = document.querySelectorAll("*:active");
var specific = active && active.length && active[active.length-1];
display("Mouse down: Most specific active element: " +
(specific ? specific.tagName : "(none)"));
}
function mouseUp() {
display("Mouse up");
}
function display(msg) {
var p = document.createElement('p');
p.innerHTML = String(msg);
document.body.appendChild(p);
}
})();
Live Copy
With all three browsers I tried (Chrome, Firefox, Opera), the element gets a red background while the mouse is down, and goes white again when I release it; but the mousedown handler doesn't see the :active element in Firefox or Opera, just Chrome.
But I'm not a CSS specification lawyer. :-)
Seems to be set after the frame has been rendered, or maybe after the current execution queue, that's at least the case with Firefox.
Got results using setTimeout without delay (works with requestAnimationFrame too):
document.addEventListener('mousedown', e => {
setTimeout(_ => console.log(document.querySelectorAll(':active')));
});
I'm trying to show/hide some of text in a button.
the button is
<button id="SOS" onmouseover="show()" onmouseout="hide();">
<p>S.O.S</p>
<div id="sos_left"> <?=$text_to_show_hide?></div>
</button>
and the javascript code is
<script type="text/javascript">
function show()
{
sos_left=document.getElementById('sos_left');
alert("mouseover");
sos_left.style.color = "red";
sos_left.style.fontSize = "28";
}
function hide(){
sos_left=document.getElementById('sos_left');
alert("mouseout");
sos_left.style.color = "blue";
sos_left.style.fontSize = "0";
}
</script>
the thing is that the mouse out alerts even when I'm mouse overing.
NOTE: I can't use jquery because the site is vbulletin based and I use this code on one of the templates.
The problem is that mouseover and mouseout events bubble up, and this means that when your cursor enters and exits from elements that are descendants of your button, the event listener defined on the button is triggered too.
What you can do is to check if the element that generated the event is actually the <button> element. Fix the DOM like this:
<button id="SOS" onmouseover="show(event)" onmouseout="hide(event);">...
Then your JS code:
function show(e) {
if ((e.target || e.srcElement).id !== "SOS") return;
...
function hide(e) {
var tgt = e.target || e.srcElement;
if (tgt.id !== "SOS") return;
// If the cursor enter in one of the descendants, mouseout is fired, but
// we don't want to handle this
if (tgt.contains) {
if (tgt.contains(e.relatedTarget || e.toElement)) return;
} else if (this.compareDocumentPosition)
if (tgt.compareDocumentPosition(e.relatedTarget)
& Node.DOCUMENT_POSITION_CONTAINS) return;
...
In Internet Explorer (and now in Opera too) there are these events mouseenter and mouseleave that behave very similarly, but don't bubble up. For other browsers they're emulated in common frameworks like jQuery.
On a final note, I'd suggest you to use some more modern method to attach your event listeners than the traditional one. Plus, the way you define sos_left implies that it becomes a global variable. Use the keyword var in front of the definition.
you dont hide anything..
use display:none to "remove" element, or visibility:hidden to hide element.
to "re-add" the element, use display: block or visibility:visible, if you used visibility attribute to hide.
try each both to see the difference.
another problem is,
you try to use sos_left as variable, but you didn't declare it as variable.
use var sos_left instead of.
That's because you apply the event to the div not the button. Try this:
sos_button=document.getElementById('SOS');
I am using a drop down widget called Chosen which has an anchor with a href javascript:void(0). When I click on the drop down it works but on IE it fires a new onbeforeunload event which is frustrating because the application confirms if you want to leave. And obviously you don't want to have those questions when you are inputting form data.
Is there a way to get rid of this problem without altering Chosen library?
Unfortunately this:
window.onbeforeunload = function (e) {
console.log(window.location);
};
Does not log javascript:void(0) either, so, I can't use it to check the target URL.
This behavior occurs in IE9 at least, and that's what I'm concerned (not the older IEs).
The only solution I can see is to add returning of false to the onclick event handler of the links. It will tell IE that you're not planning to change the page by clicking on the link.
Link
The same can be written this way:
<script>
function doSomething() {
// do Something
return false;
}
</script>
Link
I ended up listening to click events against the anchor and cancel the event to prevent onBeforeUnload from firing:
$chosen.find('.chzn-single').click(function() {
return false;
});
I know that this is pretty old...But I have come across this recently for my work. We are unfortunately still forced to support IE9. We are using Angular.js on this project that will dynamically load new content onto a page when the user clicks on an anchor tag with a data-ng-click.
In your example all you would have to do is pass the event and within the function prevent the default action and stop it from bubbling up. To do this all you would have to do is this:
// Inside the HTML
{...}
Link
{...}
<script>
function doSomething(evt) {
evt.preventDefault();
evt.stopPropagation();
// Do Something
};
</script>
{...}
In Angular all I did was the following:
// Inside the View
Add Stuff
// Inside the controller
function addStuff($event) {
$event.preventDefault();
$event.stopPropagation();
// Do Something
};
I hope that this isn't too late and I hope that it helps others.
Had the same problem. Just found your question. My solution is, you need to add onclick attribute to every chosen dropdown list anchor tag and call window.onbeforeunload = null
In my case, I've put
$(".chzn-single").attr("onclick", "window.onbeforeunload = null;");
After setting up chosen library and it works fine
don't use href's for this. A simple solution with minimal extra work:
i prefer to use a CSS class that simulates an href, obviously you will change the color and styling of this class to fit your website, but for this purposes, it's the standard blue underlined link
<style>
.linkSimulate
{
cursor: pointer;
COLOR: blue;
text-decoration: underline;
}
</style>
then use a simple anchor
<a onclick = "do_save();" class ="linkSimulate">Link</a>
Even if this question is old, i've anhanced the answer of #Bartosz, fixing the issue in the comment of #Oiva Eskola:
Wouldn't this prevent the window.onbeforeunload from working after clicking a chosen link element? – var thisOnClick;
Below is my solution to properly create the HTML onclick property, to not override or cancel the event:
var thisOnClick;
$.each( $(' .container a '), function(){
thisOnClick = $(this).attr('onclick');
if ( typeof thisOnClick == 'undefined' ) {
$(this).attr('onclick', 'window.onbeforeunload = null;');
} else if ( typeof thisOnClick == 'string' && thisOnClick.indexOf('window.onbeforeunload') == -1 ) {
$(this).attr('onclick', thisOnClick + 'window.onbeforeunload = null;');
}
});