jQuery - get part of DOM as string - javascript

I have a html code like this:
<div id="sample" style="height: 100px">
<div class="test">
...
</div>
<div class="test">
...
</div>
<div class="test">
...
</div>
...
</div>
I need to get <div id="sample" style="height: 100px"> string from this DOM. How can I do this?

Assuming you want to get the div's HTML as a string without the children in that string, an approach could be to select the element, clone it (to avoid messing with the DOM), wrap the clone in another element, crawl up to that element and take that elements contents.
var str = $("#sample").clone().empty().wrap("<div/>").parent().html();
Here's a jsfiddle-demo. So to clarify:
.clone() yields:
<div id="sample" style="height: 100px">
<div class="test">
...
</div>
<div class="test">
...
</div>
<div class="test">
...
</div>
...
</div>
.empty()
<div id="sample" style="height: 100px"></div>
Side note: From here, instead of using .wrap().parent().html(), you could fetch the original DOM-element and access the outerHTML-attribute (i.e. $("#sample").clone().empty()[0].outerHTML). However, the first-mentioned approach defies cross-browser compatibility issues.
.wrap("<div/>")
<div><div id="sample" style="height: 100px"></div></div>
.parent() refers to the newly created outer div, and .html() returns the content of that, which will leave you with the string <div id="sample" style="height: 100px"></div>

Try this
var str = $('#sample')[0].outerHTML.split('\n')[0];
alert(str);
http://jsfiddle.net/d27frp8a/

Just another way:
var element = $('#sample')[0];
var outer = element.outerHTML;
var inner = element.innerHTML;
var line = outer.substring(0, outer.indexOf(element.innerHTML));
Get the string representation of full element
Get the string representation of the content inside
Get a substring from the beginning to a shift of inner part

Related

java script replace for html attributes

I have a html tag like the following:
<div id="slide1" class="mySlides" type="slide" index="1" duration="1100" style="display: block;">
<div id="page_number1" class="numbertext">1/2</div>
<div id="slide_content1"><p>First Slide</p>
</div>
<div id="slide_h1" class="slide_h1"></div>
<div id="slide_h2" class="slide_h2"></div>
<div id="playOptions{slide_number}" class="playOptions">|
<span id="remaining_slide_time{slide_number}"></span> |
<span id="remaining_time{slide_number}"></span>
</div>
</div>
</div>
I need to replace {slide_number} with an integer. Whatever I tried the result doesn't replace the {slide_number}
var str = template.replace("{slide_number}", i);
You can use attribute selector contains that will select all elements where id contains {slide_number} and you can replace that part of the id with the number.
document.querySelectorAll("[id*='{slide_number}']").forEach(function(e) {
e.id = e.id.replace("{slide_number}", 1)
})
<div id="slide1" class="mySlides" type="slide" index="1" duration="1100" style="display: block;">
<div id="page_number1" class="numbertext">1/2</div>
<div id="slide_content1">
<p>First Slide</p>
</div>
<div id="slide_h1" class="slide_h1"></div>
<div id="slide_h2" class="slide_h2"></div>
<div id="playOptions{slide_number}" class="playOptions">|
<span id="remaining_slide_time{slide_number}"></span> |
<span id="remaining_time{slide_number}"></span>
</div>
</div>
in javascript you can find them from
document.querySelector('[id$="{slide_number}"]').id;
and
document.querySelector('[id*="{slide_number}"]').id;
Please read this
If you use jquery then it can be done like below:
$('#playOptions').attr('id','playOptions88');
But I recommend you to use HTML data attribute to distinguish different element. It is a very nice thing to work with multiple elements that can be needed to change dynamically.
If you change your ID attribute dynamically adding some integer number then it may be harder to catch them. Instead, use data like below code.
You can make any element unique setting the data-SOMETHING.
If you write the code below:
$('#playOptions').data('roll','100');
Then the element will be
<div id="playOptions" data-roll="100" class="playOptions">
If you write the code below:
$('#playOptions').data('name','ahmad');
Then the element will be
<div id="playOptions" data-name="ahmad" class="playOptions">
You can then catch the element by the code below:
var name = $('#playOptions').data('name');
console.log(name) //Output should be 'ahmad'
Similarly,
var roll = $('#playOptions').data('roll');
console.log(roll) //Output should be '100'
To learn more about the data attribute please see the link
https://api.jquery.com/data/
This solution worked:
var find = '{slide_number}';
var re = new RegExp(find, 'g');
str = template.replace(re, i);

Jquery: find element in var and change text

the following expression is not working: (neither with .text())
$(file.previewElement).find('[data-dz-name]').html(file.name);
File.previewElement is a variable = $(".preview-template").html();
For $(file.previewElement).find('[data-dz-name]')the debugger outputs:
Object { 0: <span>, length: 1, prevObject: Object, context: undefined, selector: "[data-dz-name]" }
This is about following Code:
<div class="preview-template" style="display: none;">
<div class="body content ig">
<div class="dz-preview dz-file-preview">
<h2 class="dz-filename">File: <span data-dz-name></span></h2>
<img class="dz-thumb" data-dz-thumbnail />
<div class="dz-progress"></div>
<div class="dz-error-message"><span data-dz-errormessage></span></div>
Details:
<div class="dz-size" data-dz-size></div>
<div class="dz-success-mark"><span>✔</span></div>
<div class="dz-error-mark"><span>✘</span></div>
</div>
</div>
</div>
You are using the entire HTML content as a selector, which is not valid do to. If you want your variable to be a selector change your variable to be $(".preview-template"), removing the .html() on the end.
For having file.previewElement as a separate instance variable for your HTML element you can use (as you already found out) $.parseHTML(). Which will give you a array of nodes that you can manipulate using jQuery:
file.previewElement = $.parseHTML($(".preview-template").html());
Use $(".preview-template").find('[data-dz-name]').html(file.name);
Update your code from
$(file.previewElement).find('[data-dz-name]').html(file.name);
to
$(".preview-template").find('[data-dz-name]').html(file.name);
In case you need to have variable for the element and also for the template then you have to introduce a new variable and update your code like following
file.previewElement = $(".preview-template");
file.previewTemplate = file.previewElement.html();
file.previewElement.find('[data-dz-name]').html(file.name);

How to replace strings in jQuery DOM element

I need to build HTML from an jQuery ajax response. I don't like nesting ugly strings in javascript and I don't want to use mustache or any other templating script.
So I went for the approach of having a template HTML with display: none like the following:
<div id="message-template" class="message-tile" style="display: none;">
<div class="profile-thumb"><img src="{{thumb-url}}" width="48" height="48" alt="{{person-name}}" /></div>
<div class="message-data">
<div class="message-info">
<div class="sender-name">
{{person-name}}
</div>
<div class="posted-to">
To {{posted-to-title}}
</div>
</div>
<div>{{message-body}}</div>
</div>
</div>
I want to be able to replace the strings between {{ }} with the actual values from the json object.
Suppose this is the function that gets called on the jQuery.ajax onSuccess event:
function createNewElement(jsonObj) {
var $clone = $('#message-template').clone();
$clone.replaceString("{{person-name}}", jsonObj.personName);
$clone.replaceString("{{thumb-url}}", jsonObj.thumbUrl);
$clone.replaceString("{{person-url}}", jsonObj.personUrl);
// etc
$("#target-container").append($clone);
}
I invented the replaceString method, but is there something similar? Or do I need to traverse through each element child using find() ?
Actually you can use <script type = "text/template"> to create your own templates, this way it won't render on your page:
<script id="message-template" type = "text/template">
<div class="message-tile" style="display: none;">
<div class="profile-thumb"><img src="{{thumb-url}}" width="48" height="48" alt="{{person-name}}" /></div>
<div class="message-data">
<div class="message-info">
<div class="sender-name">
{{person-name}}
</div>
<div class="posted-to">
To {{posted-to-title}}
</div>
</div>
<div>{{message-body}}</div>
</div>
</div>
</script>
Here's how you substitute your values:
function createNewElement(jsonObj) {
var $clone = $('#message-template').html();
$clone = $clone.replace("{{person-name}}", jsonObj.personName)
.replace("{{thumb-url}}", jsonObj.thumbUrl)
.replace("{{person-url}}", jsonObj.personUrl);
// etc
$("#target-container").append($clone);
}
There is a replace() method that can accept a regex, which would make it much more flexible.
Something like this would do it...
html.replace(/\{\{([^}]+)\}\}/g, function(all, key) {
return jsonObj[key] || all;
});
That way, {{personName}} would get the value from jsonObj.personName.
function createNewElement(jsonObj) {
var $clone = $('#message-template').clone();
$clone.html($clone.html().replace("{{person-name}}", jsonObj.personName));
$clone.html($clone.html().replace("{{thumb-url}}", jsonObj.thumbUrl));
$clone.html($clone.html().replace("{{person-url}}", jsonObj.personUrl));
// etc
$("#target-container").append($clone);
}

How should I edit strings across many instances of the same html?

I've got this code below, with different data, repeated over 10 times on the page I am working on:
HTML:
<div class="kpaGraph">
<p>Target: 43%</p>
<div class="progress">
<div class="bar"></div>
</div>
</div>
<div class="kpaBottom">
<div class="strong">
<p>311</p>
</div>
<div class="weak">
<p>number of teachers trained</p>
</div>
</div>
I want to alter the number in div.strong p (311) based on the number in div.kpaGraph p (43%) in the same manner across all instances of this code with Javascript/ jQuery. What is the cleanest way to do this? Should I select all $('div.kpaGraph p') and then use each() Or should I create a function and run it on all of them?
Thanks!
You can use the following to find the proper element in conjuntion with an .each() on $('div.kpaGraph p'):
$(this).parent().next('div.kpaBottom').find('div.strong p')
For example, using the following will take the value in the kpaGraph p node and append it to the p node in the following kpaBottom node:
$('div.kpaGraph p').each(function () {
$(this).parent().next('div.kpaBottom').find('div.strong p').html('foo');
});
jsFiddle example
There are a few ways.
You can use "next".
$('.kpaGraph').each(function(){
var $kpaStrong = $(this).next('.kpaBottom .strong p');//this is the elm that has 311
});
Or you have to somehow create a relation between them so you know they go together, like a common parent.
<div class="kpaWr">
<div class="kpaGraph">
<p>Target: 43%</p>
<div class="progress">
<div class="bar"></div>
</div>
</div>
<div class="kpaBottom">
<div class="strong">
<p>311</p>
</div>
<div class="weak">
<p>number of teachers trained</p>
</div>
</div>
</div>
Then with jQuery you can select it like so:
$('.kpaGraph').each(function(){
var $kpaStrong = $(this).closest('.kpaWr').find('.kpaBottom .strong p');//this is the elm that has 311
});
Something like this might be pretty clean too:
$("div.strong p").text(function(index, text){
return $(this).closest("div.kpaBottom").prev("div.kpaGraph").find("p").text();
});
That would change the text to Target: 43% in your example.

"Cut and Paste" - moving nodes in the DOM with Javascript

I have html code that looks roughly like this:
<div id="id1">
<div id="id2">
<p>some html</p>
<span>maybe some more</span>
</div>
<div id="id3">
<p>different text here</p>
<input type="text">
<span>maybe even a form item</span>
</div>
</div>
Obviously there's more to it than that, but that's the basic idea. What I need to do is switch the location of #id2 and #id3, so the result is:
<div id="id1">
<div id="id3">...</div>
<div id="id2">...</div>
</div>
Does anyone know of a function (I'm sure I'm not the first person to require this functionality) that can read and write the two nodes (and all their children) so as to swap their location in the DOM?
In this case, document.getElementById('id1').appendChild(document.getElementById('id2')); should do the trick.
More generally you can use insertBefore().
This function takes any node that is passed into it and wraps it with the tag given. In the example code snippet I wrapped a span tag with a section tag.
function wrap(node, tag) {
node.parentNode.insertBefore(document.createElement(tag), node);
node.previousElementSibling.appendChild(node);
}
function wrap(node, tag) {
node.parentNode.insertBefore(document.createElement(tag), node);
node.previousElementSibling.appendChild(node);
}
let toWrap = document.querySelector("#hi");
wrap(toWrap, "section");
console.log(document.querySelector("section > #hi"), " section wrapped element");
<span id="hi">hello there!</span>
You can use
insertAdjacentElement instead of appendChild to have more control about the position of element with respect to a target element.
Syntax: targetElement.insertAdjacentElement(position, element).
It has four position codes as:
'beforebegin': Before the targetElement itself.
'afterbegin': Just inside the targetElement, before its first child.
'beforeend': Just inside the targetElement, after its last child.
'afterend': After the targetElement itself.
it appears as:
//beforebegin
<p>
//afterbegin
foo
//beforeend
</p>
//afterend
In your case, you can write the code as:
document.getElementById('id2').insertAdjacentElement('beforebegin', document.getElementById('id3'));
Note that this way, you don't need reference the parent (container) element!
Also consider You have more elements than id2, id3, eg: id4, id5, id6. Now, if you want to reposition for example id5 after id2, its as simple as:
function changePosition() {
document.getElementById('id2').insertAdjacentElement('afterend', document.getElementById('id5'));
}
<div id='container'>
<div id='id1'>id1</div>
<div id='id2'><u>id2</u></div>
<div id='id3'>id3</div>
<div id='id4'>id4</div>
<div id='id5'><b>id5</b></div>
<div id='id6'>id6</div>
</div>
<p><input type='button' onclick="changePosition()" value="change position"></p>
In my opinion is worth adding that if you need just a visual change (the DOM will stay the same but I will change in the UI) you can use the CSS order property.
It is probably more efficient that working on the DOM like the other answers, althought again doesn't really change the DOM structure so of course is not a real answer to this question.
Example:
document.addEventListener("DOMContentLoaded", function () {
const btnEl = document.getElementById('btn-swap');
const elToSwap = document.getElementById('id2');
btnEl.addEventListener('click', e => {
elToSwap.classList.toggle("first");
});
});
.container {
display: flex;
flex-direction: column;
}
.first {
order: -1;
}
<div class="container">
<div id="id1">first DIV</div>
<div id="id2">second DIV</div>
</div>
<button id="btn-swap">swap divs</button>
Short
I just add button (at the bottom) and js to your html
id3.after(id2);
function swap() {
id3.after(id2);
}
<div id="id1">
<div id="id2">
<p>some html</p>
<span>maybe some more</span>
</div>
<div id="id3">
<p>different text here</p>
<input type="text">
<span>maybe even a form item</span>
</div>
</div>
<button onclick="swap()">swap</button>

Categories

Resources