yes i know this was ask before but i cant find the answer to my particluar problem.
this comes really close: jquery select all elements except a div and its children
but i want to select all but the div with its children inside an .on() statement, like this (simplified)
$('body').on('click', ':not(._project_overlay), :not(._project_overlay *)', globalClickHandler);
I don't get why this wont works :-/
(I also tried every variant of the above)
something like this will indeed select everything but the div and all of its children:
$('body').find(':not(._project_overlay *)')
so why on earth binds .on() to the children of the div?
please help me :(
You are using a multiple selector, which is the equivalent of a logical OR:
:not(._project_overlay) OR :not(._project_overlay *)
Therefore, it ends up matching both ._project_overlay and its descendants.
You want an AND instead, so you should simply write:
:not(._project_overlay):not(._project_overlay *)
Use :not(._project_overlay, ._project_overlay *) instead like following.
$('body').on('click', ':not(._project_overlay, ._project_overlay *)', globalClickHandler);
Related
Based on this DOM tree below when a comment reply button is clicked I need to use $(this) and then navigate to the next comment textarea .task-modal-cmt-reply-textarea
I am using jQuery and tried to use .parent().parent().closest('.task-modal-cmt-reply-textarea') and a few other combination without luck so far.
Can someone show me an efficient way to get this element into a var?
What I am trying to accomplish...
I have a click even on a comment reply button which insert a reply form into the DOM below a parent comment when the reply button is clicked using...
$document.on('click', '.cmt-reply-btn', function(e) {}
In this click event the reply form is put into the DOM with...
$parentCmtDomNode.after(cmtReplyFormTemplateHtml);
After the form is in the DOM I try to attach a jQuery plugin to it for #mention style capability using...
$('.task-modal-cmt-reply-textarea').mentionsInput({});
The problem
The #mention library works for the 1st clicked on comment form but all other reply forms do not work
another way to get a reference to that element, would be to do this:
var el = $(this).parent().parent().next().find('.task-modal-cmt-reply-textarea').eq(0);
note that the eq(0) just gives a single object back instead of an array with one element, which may or may not be necessary depending on what you want to do with it.
You need to do another .parent(), the two parent() you did only bring you up to the level of class "Activity-item Activity-comment" with data-activity-id = 12. Do another parent and you should be fine.
try this
var textarea_value=$(this).closest('.Activity-item').next('.Activity-item').find('form .task-model-cmt-reply-textarea').val();
or if its related with data-activityid = "12" so you can use
$(document).on('click','.cmt-reply-btn',function(){
var textarea_value = $(form[data-comment-parent-id = "'+$(this).attr('data-activityid')+' .task-modal-cmt-reply-textarea"]).val();
});
A more efficient way would be to use the parents api from jQuery then followed by your .closests
.parents('div')
The .parents() and .parent() methods are similar, except that the latter only travels a single level up the DOM tree. Also, $( "html" ).parent() method returns a set containing document whereas $( "html" ).parents() returns an empty set.
Then add the following sub selector to your closest chain.
.closest('textarea[name=^"task-modal-cmt-textarea"]')
This looks for the closest textarea with the name starting with task-modal-cmt-textarea. This is more efficient than what you have as this will eliminate any lookups on non textarea elements then it will only filter out the textareas that have that particular name.
EDIT: Updated Answer to the OP's recent edit.
$('.task-modal-cmt-reply-textarea').mentionsInput({});
This will select all of the ".task-modal-cmt-reply-textarea" that are on the screen at the time, it will not account for future ones. To achieve what you are looking for you should put a sub selector on this chain to allow it to attach to the newest form that was created.
$('.task-modal-cmt-reply-textarea',$($parentCmtDomNode).next('textarea')).mentionsInput({});
This should be placed after the
$parentCmtDomNode.after(cmtReplyFormTemplateHtml);
Try this:
var txt_html = $(this).parents('.Activity').children("textarea:first").html();
var txt_val = $(this).parents('.Activity').children("textarea:first").val();
In the parents() function you need to use the closest parent class/ id.
var el = $(this).parents('.Activity-item').next().find('.task-modal-cmt-reply-textarea').eq(0);
I know how to accomplish this if I can identify this element using a selector:
$("selector.class")
But what if my selector is the keyword this? Obviously $(this".class") isn't going to work, and I don't want to use $(this).children(".class") because then I need to extract the HTML of the element using .html(), and while I know that there will only be one element of this class in the selected element (I'm writing the HTML), JQuery doesn't, and it assumes that children() returns several elements when used with a class (at lease I think that's what it does, because
$(this).children(".class").html()
returns undefined).
Is there an other way I could do this?
Please feel free to ask for clarification, I understand this may not seem clear to some.
EDIT: some of you asked for clarification, so here it is. Let me rephrase the question: normally, when I ask JQuery to get me some elements, and give it a class as a selector it assumes I will get more than one element back and therefore $(".selector").html() doesn't work, because you can't get the HTML of several elements (at least that's my theory). Instead, I want it to recognise that in this case I am only getting 1 element back, and treat is as such. My restriction is that part of my selector is this. I hope that helped!
It isn't entirely clear to me what question you're asking so here are several different options:
To search for any subordinate tags (in the DOM tree with this as its root) that match a desired selector:
$(this).find(".myClass");
Or, if you're just trying to see if the this element has a particular class name, you can use:
if ($(this).hasClass("myClass")) {
// this element has the desired class
}
or, if the selector is more complicated than just a class, you can use .is() like this:
if ($(this).is("selector")) {
// this element matches desired selector
}
Really this isn't a selector, but I think you can do:
$(".class", this)
This is an example of supplying the context argument to the jQuery ($) function
For example (jsfiddle here),
HTML:
<div id="dis">hello
<div class="cls">
hi</div></div>
<div class="cls">
goodbye</div>
jQuery:
$(function () {
$('#dis').click(function () {
alert(
$('.cls', this).html());
});
});
will alert "hi" when the "dis" div is clicked.
Jquery is just a layer on top of JavaScript.
Just use raw javascript to get what you're looking for.
var childOfThis = this.querySelector('.myClass');
Is it better to attach the on() event to the document or a closer parent?
Note: Initially this question had another aspect and a different topic. It became obsolete really quickly (typo in the source code)
The best key for performance using jQuery is to use an id as the initial identifier. For example:
$('#my_id').on('click', 'tag.my_class', function () {
...
});
This allows jQuery to go straight to the container, and then begin trawling from there.
if you bind the "on" event to the closest parent will produce exactly what are you looking for, click function will works fine even if it is appended to document, but in future if you append any elements with class "clickable" will also get binded. so its always good practice to append the "on" event to closest parent rather than whole document.
if you want more specific you can use
$("ul.media-grid").on('click', 'li.clickable', function () {
alert("works")
});
as it will get the ul with the class "media-grid" and appends the event to the li's with class "clickable"
I have a table with some radiobuttons in it. When i click on a radiobutton, i want to update two of the sorrounding containers ID attribute (a div and a table). The problem is, i need to go 4 and 6 levels up, and the only way i know how to do this is parent().parent().parent().parent() etc.
I am looking for a better solution, and was hoping someone could point me in the right direction. You can see an image of how the "parent-child" tree is here:
http://imageshack.us/photo/my-images/834/imgkz.png/
I already have a clickhandler etc set up.
Basicly i need to check if the table's id attribute is "answeredTable", if not i need to change it. Also i need to check if the div two levels up from the table is "answered", if not, i need to change that too.
Thanks
You can use .closest('#answeredTable') or .parents('#answeredTable').
Using .parent() only selects the first parent element upon the DOM tree, selecting .closest() will allow you to walk up to DOM tree and match until it finds the element, while .parents() will return the whole parentset of the DOM and match the element in the whole parentset.
You need to use .parents() that go through multiple level of the DOM
For instance, in your example, you could get the surrounding div with this code:
$("#Q_18_2015").parents("div#answered")
By the way, id should be unique, or else, your code might probably not work. You should use classes instead.
<div class="answered">
Thus, the code would become:
$("#Q_18_2015").parents("div.answered")
provided that Q_18_2015 is really a unique id
I think what you want to use is closest http://api.jquery.com/closest/
you can use .parents
$("element").parent(".parentClass")
parents will go up the DOM until finds the parent with class parentClass
I use .append to add to a div
$(this).append('<ul><li>test</li></ul>');
how can I search for a <ul> and remove it if it exists in the children of $(this)?
You could use remove(). More information on jQuery remove().
$(this).children("ul").remove();
Note that this will remove all ul elements that are children.
The opposite of .append() is .prepend().
From the jQuery documentation for prepend…
The .prepend() method inserts the specified content as the first child of each element in the jQuery collection (To insert it as the last child, use .append()).
I realize this doesn’t answer the OP’s specific case. But it does answer the question heading. :) And it’s the first hit on Google for “jquery opposite append”.
Use the remove() method:
$(this).children("ul").remove();
What you also should consider, is keeping a reference to the created element, then you can easily remove it specificly:
var newUL = $('<ul><li>test</li></ul>');
$(this).append(newUL);
// Later ...
newUL.remove();
just had the same problem and ive come across this - which actually does the trick for me:
// $("#the_div").contents().remove();
// or short:
$("#the_div").empty();
$("#the_div").append("HTML goes in here...");
Opposite up is children(), but opposite in position is prepend().
Here a very good tutorial.