Jquery selector context not working [duplicate] - javascript

This question already has answers here:
jQuery() not finding elements in jQuery.parseHTML() result
(7 answers)
Closed 4 years ago.
I have a js object that has a parameter that defines the layout in HTML. While constructing the page I use jQuery to modify that layout parameter before drawing it on screen. For some reason when I try to use jQuery selectors against the object it is not finding anything.
Here I have used the browser console to show the object parameter:
$(Students_OE_Programs.layout)
(3) [div.test, text, div#student_programs_pb1_holder.pickboxHolder]
0:div.test
1:text
2:div#student_programs_pb1_holder.pickboxHolder
length:3
__proto__:Array(0)
Now I use jQuery to select all divs from this object. As you can see above there should be 2, but I get none:
$('div',Students_OE_Programs.layout)
r.fn.init [prevObject: r.fn.init(3)]
I have also tried:
$(Students_OE_Programs.layout).children('div')
r.fn.init [prevObject: r.fn.init(3)]
The most puzzling this about this is that I have done the exact same thing in other parts of the same page and it works just fine. Any help would be appreciated. I apologize if this question has been asked, I have found it difficult to search for.
Updated to include sample below. As you can see the layout contains the two divs, but the jQuery.append is not finding anything to match so it isn't appending any of the spans.
var Students_OE_Programs = {
layout: null
}
$(document).ready(function() {
var l = '<div class="test">Programs</div>\
<div id="OEPrograms_holder" class="pickboxHolder"></div>';
Students_OE_Programs.layout = $.parseHTML(l);
console.log(Students_OE_Programs.layout);
$('div',Students_OE_Programs.layout).append('<span>test</span>');
$('body').append(Students_OE_Programs.layout);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<html>
<body>
</body>
</html>

This is indeed answered by the linked question:
The $(selector, $.parseHTML(data))-style lookup uses $.find. Since I'm looking for an element that's top-level in this jQuery object, I should use $.filter instead. Voila.
In other parts of the project I am not looking for top-level elements, which works just fine.
Thank you all for your help!

Related

Javascript autocomplete in Qualtrics fails to show below the question

I've implemented the following javascript code to use the autocomplete feature within the text field question in Qualtrics.
Qualtrics.SurveyEngine.addOnReady(function()
{
var textOptions = [
"Adam", "Athelney", "Baring"
];
jQuery('.QR-' + this.questionId).autocomplete({
source: textOptions,
minLength: 3
});
});
The code works; however, the autocomplete suggestions appears at the end of the page (below "Powered by Qualtrics" URL link). See the first screenshot:
I am not sure whether this is a bug within Qualtrics; however, I've tested the same code on an account provided by a different University (see the second screenshot below) where the same code works as expected (the suggestion appears right below the question, not at the end of the page) so I am left puzzled by this behavior.
Any ideas what may cause this behavior and how to resolve it? (both examples don't use any custom CSS or such but they are accounts hosted at two different Universities) Thank you.
Based on the comment above, copy the CSS html.JFEScope body#SurveyEngineBody ul#ui-id-5.ui-menu.ui-widget.ui-widget-content.ui-autocomplete.ui-front rule from the working version to the Look&Feel>Custom CSS of the non-working version. The important part is the contents of the rule. Presumably they are different.
Although the classes are in a different order the only difference between the two selectors is the id of the ul element. Make sure you use the correct id (they may be different in the two surveys).
A bit late, but jquery autocomplete looks for .ui-front on a parent element; if it's not set you need to explicitly add a selector with the appendTo option in your custom js code for that questions.
var yourSourceList = ['foo', 'bar', 'baz'],
$elem = jQuery('.QR-'+this.questionId),
$elemParent = $elem.parent();
jQuery($elem).autocomplete({
source: yourSourceList,
minLength:3,
appendTo: $elemParent
});

How JQuery objects assigned to a variable detect changes?

(First of all sorry for my English) I can understand assigning JQuery objects that found by JQuery selectors, to a variable has better performance then using JQuery Selectors every time. The part that i cannot understand is how JQuery detects changes that are not manipulated by JQuery? Here is an example:
<div id="divState">First State</div>
$(document).ready(function () {
var testElement = $("#divState");
alert(testElement.text());//alerts "First State".
document.getElementById("divState").innerHTML = "Second State";//Div has changed outside of the JQuery object.
alert(testElement.text());//alerts "Second State"??? How a variable detects changes.
});
Well, it knows, but it doesn't know . . .
As Blazemonger points out, when you create a jQuery object, one of the items in the object is, essentially, just a pointer to the actual DOM element in the page. So, like you show in your example, any time you inspect the properties of that object, it will inspect the element and show you whatever they currently are. If they change in between checks, you will see the difference.
However, jQuery is not 100% smart . . . if you were to change something fundemental to the selector, it is not smart enough to know to update the collection of objects, without re-selecting them. For example, look at this HTML:
<div id="container">
<div class="similarDivs">Div 1</div>
<div class="similarDivs">Div 2</div>
<div class="similarDivs">Div 3</div>
</div>
If you run the following code against it:
var $mainGroup = $("#container");
var $subGroup = $mainGroup.find(".similarDivs");
console.log($subGroup);
. . . your console would show: Object[div.similarDivs, div.similarDivs, div.similarDivs]
But, if you were to follow that up with this code:
$mainGroup.children(":eq(0)").removeClass("similarDivs");
console.log($subGroup);
. . . your console would show: Object[div, div.similarDivs, div.similarDivs]
It is smart enough to see that the 1st div is no longer tagged with the "similarDivs" class, but it is not smart enough to know that, technically, that means that it should no longer be part of the $subGroup selection group. Again, this is because the selector created a bunch of jQuery objects that point to all of the DOM elements that matched the selection criteria, at a single point in time.
The only way that you could get $subGroup to reflect the change in its collection is by re-running the selector:
$subGroup = $mainGroup.find(".similarDivs");
console.log($subGroup);
. . . resulting in: Object[div.similarDivs, div.similarDivs]
One of the biggest reasons that this is so important (apart from knowing that when you use selectors :) ), is because Javascript does NOT behave that way . . . if you were to write a similar set of functionality in JS, you would get different results:
var mainGroup = document.getElementById("container");
var subGroup = mainGroup.getElementsByClassName("similarDivs");
console.log(subGroup);
mainGroup.children[1].className = "";
console.log(subGroup);
That code would give you:
HTMLCollection[div.25dd58, div.25dd58, div.25dd58]
HTMLCollection[div.25dd58, div.25dd58]
. . . without needing to "re-select" the elements (note: it is also returning an HTMLCollection, not a jQuery Object, which clues you in to the difference in behavior).
As I understand it, the jQuery object contains the DOM node, which is itself a live object. So changing the properties of the DOM node is reflected in the jQuery object.
If you were to .clone() the jQuery object, you'd get the behavior you're expecting:
$(document).ready(function() {
var testElement = $("#divState").clone(); // copy the object and store it
alert(testElement.text()); //alerts "First State".
document.getElementById("divState").innerHTML = "Second State"; //Div has changed outside of the JQuery object.
alert(testElement.text()); //alerts "First State" again
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="divState">First State</div>
jQuery is NOT a different programming language. Its a library built on Javascript.
testElement.text() do not detect any change it simply picks the text of testElement and display to alert
I am fairly certain that testElement is just instructions on how to find the DOM element using good old JavaScript, which is faster than finding it via the jQuery selectors.
So every time you work with it, it finds it anew.
Please correct me if I am wrong, that is just an assumption I have based on experience rather than knowledge.

Do custom markup tags placed in an HTML document affect the flow and is it possible to parse them with JS? [duplicate]

This question already has answers here:
Is there a way to create your own html tag in HTML5?
(18 answers)
Closed 8 years ago.
Would it be possible to do the following
<body>
<main>
<!-- CONTENT -->
</main>
<foot>
<!-- FOOTER CONTENT -->
</foot>
</body>
if I then wrote some JavaScript that did something along the lines of the following. Please note that I don't want you to write the actual code that goes here. This is just a mockup of the core functionality.
for(elem inside main){
elem.makeItBig();
}
for(elem inside foot){
if(elem is img){
elem.makeItSmall();
}
}
I am aware of this post Is there a way to create your own html tag in HTML5?. But I don't really want to create tags to style them but rather to provide identifying attributes to the DOM which I can hook into using JavaScript. Imagine something kind of like a class, but used in a way that you can stitch lots of PHP generated parts together using these tags.
If you use a made up tag in HTML is it ignored by your browser or will it throw an error.
You can use your own tags as far as I'm aware.
You'd need to do some mucking about to get them to work in older IE browsers.
The more important point is - why on earth would you want to? It wouldn't make your code very maintainable or future-proof. Just use classes on proper elements.
Can you create custom tags? yes. Is it a good idea? not really because your tag may not be recognized by some browsers as a valid html standard. you can check this: http://www.w3.org/MarkUp/html-spec/html-spec_4.html#SEC4.2.1
For custom elements specifications you can look at standards specification for custom elements : http://w3c.github.io/webcomponents/spec/custom/
Although your approach seems nice, just think about changing the size of another group of elements ... you would probably use the same function so why not do this:
var makeItBig = function(elem){...};
for(elem in main){
makeItBig(main[elem]);
}
this way you won't have to create a new method for each element you need to change.
But if you really need it that way you can make it like this:
var makeItBigFunction = function(){var elem = this; ...};
// create new methods
for(elem in main){
main[elem].makeItBig = makeItBigFunction;
}
// make use of them
for(elem in main){
main[elem].makeItBig();
}
Notice that there is a big difference between DOM object's properties (or methods) and HTML attributes.
Read more about it: Properties and Attributes in HTML
Feel free to use HTML5 tags like <content>, <header>, <footer>, <aside> etc.
You can read more about them here: http://www.w3schools.com/html/html5_new_elements.asp in section "New Semantic/Structural Elements". Those should be considered as supported in most modern browsers. Actually, you may use any other custom tags, however their default properties (display, position etc.) may be unpredictable.

Create drop-down list using JavaScript instead of HTML

I have the following code that creates and deletes text boxes using javascript:
http://jsfiddle.net/JpYGg/8/
What I am aiming to do is infact create a set of three drop-down lists using this functionality instead of creating a textbox.
The code for the three drop-downs is shown here:
http://jsfiddle.net/MWH99/
I am a bit stuck as to how to achieve this. I added in the "dropdown" div and what I was thinking is to get the innerHTML of this div in order to use that to create the three lists every time?
The other question I have is how to have it so that these are generated by the javascript instead of an HTML one AND a JavaScript version.
Thank you for any help.
Martin
EDIT
I have the buttons working to create the next row of 3 drop-downs but they do not function the way that the original does, the parent drop-downs use javascript to identify the selection in the first drop-down in order to update the other two whereas the cloned ones lose this functionality.
Code cna be found here:
http://pastebin.com/pt1wef76
Original drop downs use dropdown.js which is http://pastebin.com/bDLpFWJY
Why not use a javascript library like jQuery for example. Would make this and many other things much easier. Could achieve what you want like this:
$('body').append('<!-- ANY HTML GOES HERE -->')
There's two basic approaches; create all of the elements in JavaScript, or copy a part of the DOM (some HTML) over and over.
People often put HTML in script tags (see jQuery Templating, for example), and then get the innerHTML of the tag and use that. For example,
<script type="text/plain" id="template">
<!-- HTML that you want to duplicate in here -->
</script>
<div id="contentcontainer">
</div>
...
<script type="text/javascript">
var addAnother = function( ) {
$("#contentcontainer").append(
$("#template").html()
);
};
</script>
This example makes use of jQuery primarily because jQuery is a lot less verbose and easier to read, but you certainly don't have to use jQuery. Here, the addAnother function will copy the HTML from #template and append it into #contentcontainer.
In your attempt above, you probably meant $('body').append($('#dropdown')); '#dropdown' is just a string, $('#dropdown') returns the element (or elements) with id="dropdown".

Append custom attributes to a DOM node [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Can I just make up attributes on my HTML tags?
Hi,
I am not sure if what I am asking is even possible, but I'd like to be able to add a custom (nonrendered) propery to an existing HTML DOM node.
For example, if I have a simple DOM as below:
<body>
<p>
<span id="aSpan"></span>
</p>
</body>
.. I'd like to be able to add a custom property to the span 'aSpan' to store a numeric variable.
Is this possible and if so, what is the best way to do it?
Thanks,
Sure, I do this all the time. You can do it in the html:
<span id="aSpan" attname="attvalue">
(validators don't like this though, technically it's not valid html but it works)
Or via javascript:
element.setAttribute('attname', 'attvalue');
You can read it with:
element.getAttribute('attname');
Take a look at the duplicate question for reasons why not to do this this and restrictions on how it can be done legally in HTML 5.
Despite the validation errors you'll receive, using jQuery you can make use of the $.attr() function:
$('.element').attr('foo', 'bar')
I'm not sure in plain Javascript, but jQuery has the data function.
$('#aSpan').data('foo', 69);
alert($('#aSpan').data('foo'));
a simple way.. if your page is dinamic.. you can simply add a value to your ID
a little example if I understand well, you can use it in a class, supposed we have a 56 has ID
<body>
<p>
<span id="aSpan" class="A54F23345A56A23524234"></span>
</p>
</body>
I do simply made a string the ID 'A54F23345A' + 56 + 'A23524234'
But you can use it has you wish.. and the id is hidden from users.. you can use more secure script.. but if isn't a security issue.. it works like a charm ^^
Have a nice day

Categories