Get position of an element within DOM structure - javascript

Is there any solution on how to determine object's position within DOM structure? Normally I'd use XPath but document.evaluate() is not cross-browser compatible so I'm throwing that off.
Sample page HTML:
<html>
<head></head>
<body>
<div>Some element 1</div>
<div>Some element 2</div>
<div>
<p>some text 1</p>
<img src="#">
<p>some text 2</p>
</div>
</body>
</html>
Now imagine user selects text "text 2" within second paragraph. What I need is to get something like /html/body/div[3]/p[2][.='text 2'] and save it via $.ajax() in database. When user enters the same page again (somewhere in future) I need to highlight text "text 2" again and scroll the second paragraph into view (probably using window.scrollTo()).

Related

Optimal way to retrieve HTML nodes having text using JavaScript/JQuery

How to get all the HTML nodes having text in an optimal way without having to loop through every node?
In other words, grab all HTML nodes having visible text.
For example, if I have a dom as below
<div>
<span>Hello This is a Text Span</span>
<div>
<p> This is a text Paragraph</p>
<button> This is Button Label</button>
</div>
<div> This is also a visible text</div>
</div>
I should select
span having text Hello This is a Text Span
p having text This is a text Paragraph
button having text This is Button Label
div having text This is also a visible text
The outermost div in the above example doesn't have text of its own so should not be part of the result.
Edit: What problem am I trying to solve?
The framework I use escapes HTML characters in labels of fields, buttons, headings etc.
For example: < is converted to & lt;'
So I am trying to write a client side code which triggers after the page is completely rendered which will unescape all the HTML texts to a readable format.
Any help will be appreciated.
Thanks in advance
The DOM property holds a numeric code indicating the node's type; text nodes use the code 3, So you can find those text nodes by filtering them having nodeType 3.
Wrap your all nodes in a div by giving a class.
Select your content by it's class like this: $(".getTextNodes").contents();.
Filter contents having nodeType 3.
selectedElement = $(".getTextNodes").contents();
textNodes = selectedElement.filter(function() {
return this.nodeType === 3;
});
console.log(textNodes);
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha256-9/aliU8dGd2tb6OSsuzixeV4y/faTqgFtohetphbbj0=" crossorigin="anonymous"></script>
<div class="getTextNodes">
<span>Hello This is a Text Span</span>
<div>
<p> This is a text Paragraph</p>
<button> This is Button Label</button>
</div>
<div> This is also a visible text</div>
</div>
Check this link out to read more.
I'm using just only vanilla js
My algorithm is just select all element that has no element inside it
It means select all element that has directly Text Node
let el = document.querySelectorAll('div,span,p,button');
var arr = [];
el.forEach(function(m){
if (m.querySelectorAll('div,span,p,button').length == 0){
arr.push(m)
console.log(m)
}
})
// console.log(arr)
<div>
<span>Hello This is a Text Span</span>
<div>
<p>This is a text Paragraph</p>
<button> This is Button Label</button>
</div>
<div>This is also a visible text</div>
</div>
Jsfidle link click here
There's no css selector to get your needs and looping is only the solution.

Toggle Display on/off

I am using JQM and I have a situation where I have HTML generated dynamically. It's possible, even probable that the same HTML will be used in more that one place on the page. I have a div with data in it that I only want to be displayed when the user clicks the header div. IE:
<html>
<head>
<style>
</style>
<script src="/js/jquery.js"></script>
</head>
<body>
<div onclick="$(this).children('div:first').toggle();">This is Div 1</div>
<div style="display:none">
<p>I'm hidden</p>
</div>
</div>
</body>
</html>
What I'd like to do is when the user clicks on the Click Me link the child toggles its display on and off. Any thoughts on how this can be accomplished without some convoluted ID scheme? (I've thought of at least two).
According to the code you posted, the div containing "I'm hidden" is not a child of the first div.
You can use $.eq() to select a specific children index: https://api.jquery.com/eq/
<div onclick="$(this).children('div').eq(0).toggle();">
This is Div 1
<div style="display:none">
<p>I'm hidden</p>
</div>
</div>
See working JSFiddle (with "hidden div" child of Div1)
If you need to toggle visibility of a sibling, you can use $.siblings() https://api.jquery.com/siblings/ or $.next() https://api.jquery.com/next/
<div onclick="$(this).next().toggle();">
This is Div 1
</div>
<div style="display:none">
<p>I'm hidden and I'm a sibling</p>
</div>
See JSFiddle2 (hidden div sibling of Div1)
you can tie an event to the Click Me and in javascript/jquery, find the first child div after "this" (the div that was clicked). Something like this:
$(this).children("div:first");

Onclick HTML Div

I have a text to speak script and it is called by Javascript on HTML like this;
<head>
<script src="speakClient.js"></script>
</head>
<body>
<button onclick="speak('type text to speak here')">Talk</button>
<div class="article">
<p>Sample text is here!!</p>
</div>
<div id="audio"></div>
</body>
Currently when 'Talk' button is pressed, the predefined text (in this case "type text to speak here") will be speak by TTS.
How to change it when button is pressed, it speaks whatever text inside div.article instead of predefined text?
Edit: Link to JS https://github.com/kripken/speak.js/blob/master/speakClient.js
Thanks in advance
You can get the textual content of an element easily with jQuery:
var textToSpeak = $('div.article').text();
Then set the onclick function dynamically:
<button onclick="speak($('div.article').text())">Talk</button>
It is better than using pure JavaScript and innerHTML property, as potential HTML tags will be stripped with this solution.
<div class="article">
<script>var text = "Sample text is here!!";</script>
</div>
<button onclick="speak(text)">Talk</button>
Give an id to the <p> tag, and then you can pull out the value by calling innerHtml.
Example:
<button onclick="speak(document.getElementById('textToUse').innerHTML)">Talk</button>
<div class="article">
<p id="textToUse">Sample text is here!!</p>
</div>
Try adding the following script to the element of which you want the text read.
onclick="speak(this.innerText);"

load second content onclick in a specific div

I am trying to make a page with some fact boxes, so I have made these divs with classes on with two tag text blocks, the second block have 'display none' on it and should first be shown when you click on the div.
And that's my problem I would like to make a Jquery function that loads the second paragraph in when I click on the div i just don't know how to tell the site that its specifically that' paragraph without using any id or classes that would trigger all the other divs.
here is my code:
<div id="content">
<div class="teaser-box">
<p>TEXT TEXT TEXT TEXT</p><!-- paragraph 1 (shown) -->
<p>TEXT TEXT TEXT TEXT</p><!-- paragraph 2 (not shown) -->
</div>
<div class="teaser-box">
<p>TEXT TEXT TEXT TEXT</p><!-- paragraph 1 (shown) -->
<p>TEXT TEXT TEXT TEXT</p><!-- paragraph 2 (not shown) -->
</div>
<div class="teaser-box">
<p>TEXT TEXT TEXT TEXT</p><!-- paragraph 1 (shown) -->
<p>TEXT TEXT TEXT TEXT</p><!-- paragraph 2 (not shown) -->
</div>
<div id="load-teas"><h4>Load more</h4></div>
</div><!-- content END -->
Thanks!
You can use another Jquery Selector like :nth-child, in your function like this:
$(document).ready(function () {
$('.teaser-box').click(function () {
$('p:nth-child(2)',this).show();
})
})
The demo http://jsfiddle.net/KC63V/4/
whenever a div is clicked, you get reference to the div in this
now you just need to find the last child of this div and show it
something like:
$('.teaser-box').click(function() {
$(this).children(':last').show();
return false;
});
Bind click on each boxes and show the second p child of the box (eq(1))
$(".teaser-box").click(function(){
$(this).find("p").eq(1).show();
}

How to make two or more html elements behave as a single unit in editable area

Consider you have some contenteditable area with some content:
<div contenteditable="true">
<p>first paragraph</p>
<p>
<img width='63' src='https://developer.cdn.mozilla.net/media/img/mdn-logo-sm.png'>
<img width='63' src='https://developer.cdn.mozilla.net/media/img/mdn-logo-sm.png'>
</p>
<p>second paragraph</p>
</div>
If you start navigate by left/right arrow keys caret start moving through all child elements. Please look this gif animation
The question is how to make caret ignore child elements? Or in any words: How to make behaviour of two images inside as a single image?
jsfiddle
try changing the <p> containing the two images to a <div> with content editing turned off.
<div contenteditable="false">
<img width='63' src='https://developer.cdn.mozilla.net/media/img/mdn-logo-sm.png'>
<img width='63' src='https://developer.cdn.mozilla.net/media/img/mdn-logo-sm.png'>
</div>
demo - http://jsfiddle.net/tfdMt/

Categories