Here is my HTML snippet.
<div id='advanced'>
<a id='javscript'>testing</a>
</div>
I need to find the parent node given the innerhtml testing.
As others have said you may want to consider re-thinking whatever it is you're trying to achieve. Anyway, if you need to do just one lookup then you just need to iterate over each node in the DOM tree and test your string against the text content. If you need to do it multiple times then this will get very slow. So a possible solution is this: loop over the DOM and put the innerHTML into a hash, with the text as the key (field) and the parent node as the value. Then for any text you can test against the hash, returning the parent node if it exists. But - don't just bang in every innerHTML for every node - this will result in a large object. If it's just text nodes you're after then only stick these into your hash.
You might want to consider going with a library, specifically jQuery.
It would make this type of search very easy for you.
This should work:
http://api.jquery.com/contains-selector/
Related
This problem that I'm facing is common for me and I want to learn for about best practices.
My problem is:
I have to wait a text which has an attribute of ".title" class and the text involves the statement of: "Hello". Before triggering this element to come to surface, we have an element already have attributes of ".title" which have a text of "StatementX" as well (At the end of the process, I have 2 ".title" class items on screen).
When I tried to wait for the element "Hello", I write:
`cy.get('.title').contains('Hello').should('be.visible')
`
Since "StatementX" is already on the screen, Cypress finds ".title" class and does not check "contains" part. What is the best practice to handle such cases?
Thank you so much
If you move the class .title into command .contains() it will focus solely on the element you wish to test, i.e two criteria will be tested in one command call and it will find the specific element.
cy.contains('.title', 'Hello').should('be.visible')
If you don't have any difference at all in those elements you will have a return of an array of elements.
In that part .eq(NUMBER OF THE ARRAY) you can validate the option that you want.
Also you can use XPATH for those cases. Not recommended since it's volatile but since is old stuff that is not changed it should have an higher change of stability.
I am in search for an efficient method to replace a couple of DOM Elements - if possible in one action only.
It is needed for augmenting TextNodes. If a certain word is present, it shall be wrapped in span-Tags, to which an event handler needs to be assigned later.
so if a text Node contains the word it needs to turn from
-#textNode
to
- #textNode
- span
- #textNode
- #textNode
While leaving the rest of the document untouched.
Known/assumed issues:
- innerHTML would be fast, but the Elements would need to have a generated ID and be later retrieved later again via getElementByID; not the cleanest/fastest way.
- Cloning the node, putting it into an documentFragment, doing all operations and replacing it back again would be good – but cloning does discard event handlers as far as I know. Since this code is to be used in an Bookmarklet/Add-On this is not an option than.
Use the DOM Level 1 Core method splitText on the Text node, once on the point just after the target text then once just before. createElement a new span, replaceChild the middle Text node (containing the target text) and appendChild that Text node into the span. Add event handlers etc. to the span as necessary.
No need to start messing with innerHTML or clever Range/adjacentHTML hacks; you're not really going to get any faster than this. Don't believe the hype: DOM manipulations like splitText or a single insertion aren't slow at all. It's only when you try to manipulate a lot of contiguous nodes all at once that other methods can improve matters.
I've a jQuery object and I shall retrieve the next sibling node, which may be a text node.
For example:
<div id="test">some text<br/>other text</div>
var test = $("#test");
var br = $("br", test);
alert(br.next().length); // No next ELEMENTS
alert(br.get(0).nextSibling.nodeValue); // "other text"
alert(br.get(0).nextSibling.nextSibling); // null
The DOM level 2 allows to get the next NODE sibling, but jQuery next() works on elements (nodeType 1, I guess).
I am asking this because I'm already using jQuery and I prefer to don't touch the DOM nodes directly (also because jQuery itself may provide a layer of abstraction from DOM and may run where DOM level 2 is not supported, but this is only a thought).
If jQuery doesn't provide this, shall I use DOM like above, or there are better options?
EDIT: I forgot something: I don't want to get ONLY text elements, but any kind of node, just as nextSibling does.
I'm using .contents() to iterate over the content, but this is pretty annoying (and slow, and many other bad things) when you just need the next node and DOM provides a solution.
EDIT2: Looking jQuery source code, it seems it relies on nextSibling.
Use the DOM. Don't be scared of it; it's easy and you already seem to know what to use. jQuery is built on top of the DOM and for this kind of thing, using the DOM will in fact work in more browsers than the jQuery version.
To my knowledge, there is no method in jquery like nextSibling in javaScript which also returns text elements.But you can go to the parent element and use contents() as it will also consider text elements.
I want to write a select something like...
#window_4 > content > p:eq(0)
I think I have this correct, but I have a few selectors that are all similar but I can't test them all at once.
Am I right in saying this is selecting an element, who is the fist p tag child of a content tag that is a child of a tag with id 'window_4'
If I have gotten this wrong, can you give me some pointers. Would love to be able to simplify this code, I have more code selecting the tag I am after then actually doing stuff with them.
Looks good to me, although you can make it a bit more readable by substituting p:eq(0) for p:first.
Edit for comment:
jQuery always returns an array of elements, no matter whether 0, 1 or many elements were found. On these elements, yes, you can perform JS functions, such as innerHTML. You can access each element returned by jQuery just as if you would any other array:
$(".red")[0].innerHTML = "Glen Crawford";
More info: http://groups.google.com/group/jquery-ui/browse_thread/thread/34551a757f139ae1/20111f82c2596426
Given the following markup.
<div id="example">
<div>
<div>
<input type='hidden'></input>
</div>
</div>
</div>
How can I quickly get the hidden input element given I have the ID for the top most div element with the ID 'example'?
I can hack away at it so I can just iterate through each child element until I hit the input, however, I'd like to improve on that and utilize Prototype and simply jump to that hidden input given the div.
Thanks!
Prototype provides a whole bunch of ways to do this:
// This, from Bill's answer, is probably the fastest, since it uses the
// Browser's optimized selector engine to get straight to the element
$$('#example input[type=hidden]').first();
// This isn't bad either. You still use the browser's selector engine
// To get straight to the #example element, then you must traverse a
// (small) DOM tree.
//
// element.down(selector) selects the first node matching the selector which
// is an decendent of element
$('example').down('input');
// Here, you'll get an array containing all the inputs under 'example'. In your HTML
// there is only one.
$('example').select('input')
// You can also use element.select() to combine separate groups of elements,
// For instance, if you needed all the form elements:
$('example').select('input', 'textarea', 'select');
$$('#example input[type=hidden]').first()
I prefer the direct approach
document.forms[0].fieldName.value
Which is less code, no need to use jQuery and is more friendly to code design.