This is my jquery scenario:
User click on div
It triggers an ajax call to save some data on DB
when callback received, we show an update msg <--everything good
until here
Now, when user click on the same element, it shows the information
from the DB, the same should happen with the other divs!
Noticed that when you click, the same text that you saved later is showing up in all the divs!!! it is not refreshing, but the actual source IS showing
the changes!
It looks like only the DOM is not reflecting the changes!
I am trying to put the text in the divs using .text();
All the divs are using the same element id!, I am just updating its data!
Thanks,
Marco
All the divs are using the same element id! - never ever should two elements have the same ID, because it breaks the principles on which HTML is built on and 3rd party libraries rely on.
If you need to target multiple elements use classes.
In case your elements have the class yourClass and you want to set them the text "foo", then
var yourResponseText = "foo";
$('.yourClass').text(yourResponseText);
Especially if you use jQuery - the ID selector is implemented in such way, that when it finds an element with that ID it doesn't look for another - the settings will only affect the first (from the viewpoint of DOM) element. On the other hand, when you're using the class selector, then simply said you're doing a forEach cycle through the elements with that class.
Related
I have multiple buttons on the same page with same id so basically
rendering in a for loop with same id . I set a click event handler in
jquery but it fires for only the first button.
Can you suggest?
You can see the error in console, which probably would be because of same ID for all the buttons. One solution would be to append the index to the button id string so that each button will have unique id(btn1, btn2 etc), or use the class instead of id.
Duplicating ids are causing your HTML to be invalid. Javascript (and jQuery) assumes that there is a single id, therefore:
$("#yourid")
will not search for the id further.
You can sidetrack the issue via
$("[id=yourid]")
which will find all the elements, but that's not advisable, because then your HTML is still invalid. A better approach would be to change your id into a class and use that as a selector afterwards.
EDIT
In jQuery you can create a click event like this:
$("[id=saveFavorite]").click(function() {/*...*/})
But even though this will work, I recommend refactoring your code, changing the HTML you have by replacing every id="saveFavorite" to class="saveFavorite" and do it like this:
$(".saveFavorite").click(function() {/*...*/})
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 want to inject some html using jQuery, just before some element like this:
$(element).before(content);
This content has some typeahead controls, so I need to call:
$('.ajax-typeahead').typeahead( ....
to make these control to become "typeahead".
The problem is that my page already had some Typeahead controls already configured and calling above command, mass all of them.
There is a way to apply this command only in the new content?
Before injecting the newly generated HTML element, attache the event handler to them.
$(element).before($('new content').find('newly created selectors').typeahead());
There are two main ways to achieve this: one is to call typeahead on the content prior to insertion into the DOM. The content has to be a jQuery object, e.g. $('<div>...</div>') or the likes.
var newContent = content.find('.ajax-typeahead').typeahead(...);
$(element).before(newContent);
However, this trick may fail under certain circumstances, such as for plugins that require computation of element dimensions — element dimensions are not computed prior to DOM insertion.
The alternative method is to perform DOM transversal using .prev(). However, not knowing how your content is, it might be a good idea to wrap them with a <div> or a semantically relevant element (e.g. <article>, <section>...)
$(element)
.before(content.wrap('<div />')) // Wrap content in <div> and insert prior to $(element)
.prev('div') // Transverse the DOM to access the inserted <div>
.find('.ajax-typeahead') // Find element with the class .ajax-typeahead
.typeahead(...); // Call typeahead()
I'm trying to further my understanding of traversing and correctly using $(this).
I understand $(this) is used in reference to the context. However, say I have three items that are identical to each other (HTML-wise) and if a user clicks on an input, I want the events to not only happen for the item the user selected, but be able to access the parent element ".item" as well. This way, I can hide other elements within ".item" because, again, the context would be the "input" that the user clicked.
This is where I am confused. When a user clicks on the input ($('input').on('click', doSomething);), I am limited to the context of the input - nothing is inside the input, so I want to access other elements that are out of the input context.
I then try and use $(this) to say I only want THIS event to happen for THIS item only, not affecting ALL items.
Here is a code example: JSFIDDLE
I've tried researching this and I can't find much information on an instance like this so hopefully this could benefit others too. Feel free to make edits to the content / heading as I've tried to be as specific as possible.
To get the immediate parent(s) of the element(s) in a jQuery set: parent. (If your set has only one element, as $(this) will, that will give you that element's immediate parent.)
To find the closest element(s) to the elements(s) in a jQuery set matching a given selector, starting with the current element(s): closest. (If your set has only one element, as $(this) will, that will give you the first element matching a selector starting with that one element, then looking at its parent, then its parent, etc.)
This should be your click-handler code :
function doSomething(event) {
$(event.target).parent().find('ul').hide();
}
Dojo converts several "ordinary" input elements into a more complex node structure. For example, a Dojo dijit/form/Select results in a widget composed of a table instead of a <select> element. dojox.form.Uploader converts into something where the id is mapped to a span and not to a <input id="myId" type="file" element. etc etc.
For accessibility, I need to map a label to an input widget, and running my website through Wave generates a lot of red flags because label for values do not match an input id.
What's the best way round this issue?
You can set an id property on most widgets, which should be put on the inner <input> node that you desire. Take a look at this fiddle for an example. If you open up your HTML inspector for the TextBox widget, you will see that the outer node has an id of "widget_[my id]" and a widgetid of the id you passed to the widget. Digging into the contents of that outer div, you will see that the actual <input> element indeed has the desired id that I passed in.
However, it seems that for more complex widgets that use a hidden <input> to store the value, you have to explicitly set the id of the valueNode property. You can see an example in this fiddle.
So you can create your widget like programmatically like this:
var select = new Select({
... widget properties
});
select.valueNode.id = "my_id"; // probably best to use dom-attr to set this.
If your widget is created declaratively, then you will need to get access to it via the registry, an attach point, or dijit#byId.