I have an jsTree, data comes from HTML
$("#tree_container").jstree();
Now I want to implement deep linking on the tree elements. I am getting the class and data-id from URL parameters and now I want to select the correspondent node.
var id=$("#tree_container").find("li."+get_class+"[data-id='"+get_id+"']").attr("id");
if(id!=undefined && id!=0) {
treeElem.jstree(true).select_node(id);
}
This only works if the node is already in the DOM Tree.
(sub-Trees are getting inserted in if the parent node is clicked)
If the node I want is not in the tree ... id is undefined and the select fails.
Thing is, if I put in the id (like "#j1_6") in directly the node is found even if it is not in the DOM tree. It only work with the Id in that format, I try putting other selectors in or even elements ($(".class[data-id='1']"), nothing worked.
My problem is that I do not know how to get the id of the node if it is not in the DOM Tree yet. I did not find a api function or anything to do that.
====== UPDATE ======
I found a workaround ...
When building the HTML tree I now combine the class and data-id to make up the html id of the element (li).
So I have controll over the ids and know them and just do:
treeElem.jstree(true).select_node("#"+get_type+"_"+get_id);
so yeah, as I said for me it is just a workaround...
Related
New to Stack Overflow and Lit.
I'm building something using Lit and wanted to know how do I render element/s only if a parent element is present. I am trying to add a login element dependency which will let user to use these elements only if the login element is present.
Example of what should be allowed.
<login-element>
<child-element-button> </child-element-button>
</login-element>
Example of what should not be allowed.
<child-element-button> </child-element-button>
Another problem that I have is a way for the child elements to share data, it can be to and from sibling elements, children elements, grandchildren element and so on. I do not have a solution for data sharing currently and would like to know the possible ways to achieve this.
Is there a way to achieve all of this without making <login-element> the parent element? something like this?
<login-element> </login-element>
<div> ... </div>
<my-custom-button> </my-custom-button>
<p> ... </p>
<my-colors> </my-colors>
<my-custom-footer> </my-custom-footer>
In short, I need users to be able to use custom elements only if <login-element> if present anywhere in the document and the custom elements that are present should be able to communicate between each other. For instance, a <my-colors> element should be able to send active color data to <display-image> element which will render an image with a specific background color received from `.
Currently, I read the child elements of <login-element>, copy the nodes, run loop, delete original nodes and append with those copied nodes. Additionally, in every child elements, I check if <login-element> is present in DOM or not, if present, render, else render a error element. As for passing and receiving data to and from other components, I have not tried anything.
Than you for your time.
Here is a part of my html. (it is written using ejs)
<div class="objAddDiv">
<tr><td><button class="addObj">Do this action</button></td></tr>
<table><div class="objects"></div></table>
</div>
I have several objAddDiv divs on this page. Each has the same structure inside of it. I use .append() to add more ejs to .objects. I am having a hard time adding to only the .objects div that is inside of the same div as the button. I tried doing the following
".addObj click": function(el, element){
$(".addObj").closest(".objAddDiv").find(".objects").append(//my ejs utility here)
}
The problem is that $(".addObj").closest(".objAddDiv") returns all .objAddDiv on the page. I have looked at the jquery documentation for .closest and it says closest should only return one element. Is there a better way to do this? What am I doing wrong. (these are not my real class names btw)
It's because you are calling that method on every element with a class of 'addObj':
For each element in the set, get the first element that matches the selector by testing the element itself and traversing up through its ancestors in the DOM tree.
So you get the closest objAddDiv to each addObj element.
Assuming you are doing this inside the click event of the button use this to get the correct element:
$(this).closest(".objAddDiv").find(".objects").append(//my ejs utility here)
Here is the answer that I figured out (for anyone who comes next) I needed to use the element I passed into the function:
el.closest(".objAddDiv").find(".objects").append(//ejs append stuff)
I just read this article about NodeLists:
http://www.nczonline.net/blog/2010/09/28/why-is-getelementsbytagname-faster-that-queryselectorall/
If I understand correctly getElementsByTag name is live and querySelectorAll is not.
Then could someone please explain to my why pNotLive has the title 'stackoverflow'? :
var pLive = document.getElementsByTagName( 'p' )[3];
var pNotLive = document.querySelectorAll( 'p' )[3];
pLive.title = "stackoverflow"
console.log( pNotLive.title ); // stackoverflow
//you can run this snippet in your console to verify
As your link explains, the getElementsByTagName method returns a collection that is automatically updated when the DOM changes. So if you call the method, and then a new element is added to the DOM, your collection will automatically be updated with the new element.
Where as, if you use querySelectorAll, you will be given a static list of DOM elements, that will NOT be updated automatically.
I believe the reason for the behaviour you have used in your example is because the list is static, and not the elements themselves. So the static approach just means the list will not change, so adding/removing elements will not change your list. But when you call for the title attribute, your list is simply pointing to the element, and that element is different from when you created the list.
In short, it is more of a list of references (to the DOM nodes), than a list of data objects (with the fixed data).
This is the same question as this:
Referring to a div inside a div with the same ID as another inside another
except for one thing.
The reason there are two elements with the same ID is because I'm adding rows to a table, and I'm doing that by making a hidden div with the contents of the row as a template. I make a new div, copy the innerhtml of the template to my new div, and then I just want to edit bits of it, but all the bits have the same ID as the template.
I could dynamically create the row element by element but it's a VERY complex row, and there's only a few things that need to be changed, so it's a lot easier to just copy from a template and change the few things I need to.
So how do I refer to the elements in my copy, rather than the template?
I don't want to mess up the template itself, or I'll never be able to get at the bits for a second use.
Or is there another simpler way to solve the problem?
It will probably just be easiest when manipulating the innerHtml to do a replace on the IDs for that row. Maybe something like...
var copiedRow = templateRow.innerHTML.replace(/id=/g,"$1copy")
This will make the copied divs be prefixed with "copy". You can develop this further for the case that you have multiple copies by keeping a counter and adding that count variable to the replace() call.
When you want to make a template and use it multiple times its best to make it of DOM, in a documentFragment for example.
That way it doesn't respond to document.getElementById() calls in the "live" DOM.
I made an example here: http://jsfiddle.net/PM5544/MXHRr/
id's should be unique on the page.
PM5544...
In reality, there's no use to change the ID to something unique, even though your document may not be valid.
Browsers' selector engines treat IDs pretty much the same as class names. Thus, you may use
document.querySelector('#myCopy #idToLookFor');
to get the copy.
IDs on a page are supposed to be unique, even when you clone them from a template.
If you dynamically create content on your page, then you must change the id of your newly cloned elements to something else. If you want to access all cloned elements, but not the template, you can add a class to them, so you can refer to all elements with that class:
var clonedElement = template.cloneNode(yes); // make a deep copy
clonedElement.setAttribute("id", "somethingElse"); // change the id
clonedElement.setAttribute("class",
clonedElement.getAttribute("class") + " cloned"
);
To access all cloned elements by classname, you can use the getElementsByClassName method (available in newer browsers) or look at this answer for a more in-depth solution: How to getElementByClass instead of GetElementById with Javascript?
Alternatively, if you have jQuery available, you can do this is far less lines of code:
$("#template").clone().attr("id","somethingElse")
.addClass("cloned").appendTo("#someDiv");
The class lookup is even simpler:
$(".cloned").doSomethingWithTheseElements();
Try to avoid using IDs in the child elements of the cloned structure, as all ids of the cloned element should be changed before adding the clone to the page. Instead, you can refer to the parent element using the new id and traverse the rest of the structure using classnames. Class names do not need to be unique, so you can just leave them as they are.
If you really must use ID's (or unique "name" attributes in form fields), I can strongly suggest using a framework like jQuery or Prototype to handle the DOM traversal; otherwise, it is quite a burden to resolve all the cross-browser issues. Here is an example of some changes deeper in the structure, using jQuery:
$("#template").clone().attr("id","somethingElse")
.addClass("cloned") // add a cloned class to the top element
.find("#foo").attr("id","bar").end() // find and modify a child element
.appendTo("#someDiv"); // finally, add the node to the page
Check out my ugly but functional cheese. I wrote a function that works like getelementbyid, but you give it a start node instead of the document. Works like a charm. It may be inefficient but I have great faith in the microprocessors running today's browsers' javascript engines.
function getelement(node, findid)
{
if (node)
if (node.id)
if (node.id == findid)
return node;
node = node.firstChild;
while(node)
{
var r = getelement(node, findid);
if (r != null)
return r;
node = node.nextSibling;
}
return null;
}
When you copy the row, don't you end up having a reference to it? At that point can't you change the ID?
I need to find all dijit.form.CheckBox widgets inside a DIV and enable/disable them all. I am not able to form appropriate query for it.
I tried dojo.query("[dojoType~=dijit.form.CheckBox]") but it gives me an empty list.
What is the appropriate query for it? Can DOJO query return a WidgetSet or does it always returns DOM ids? Is there some different way for querying dijit widgets?
Try dijit.findWidgets:
Search subtree under root, putting
found widgets in outAry. Doesn't
search for nested widgets (ie, widgets
inside other widgets)
This is 1.7 > code and will search recursively for widgets instead of just direct descendents as is the case for findWidgets
need to require "dojo/query" and optionally "dijit/registry"
var checkboxes = query("input[type=checkbox]:checked", "myForm");
checkboxes.forEach((function (checkbox) {
//dom node
console.log(checkbox);
//dijit
console.log(registry.byId(checkbox.id));
}));
This queries checked checkboxes underneath a dom node id myForm and loops through the results and prints the element. Note that this only gives dom node elements in the result set so if you want to get the dijits you can use registry.byId(...)