Get elements from source code stored in variable - javascript

I have this piece of code:
chrome.runtime.onMessage.addListener(function(request, sender) {
if (request.action == "getSource") {
message.innerText = request.source;
}
});
I need to get the text from an element which is in that source code. For example, consider the page having an element like:
<a class="something">something goes here</a>
I need to get that text of class 'something' with JavaScript. The request.source returns the source code with structure as it is.

You should be able to turn the source code into jQuery object and use it like usual from there.
var requestedSource = request.source;
$(requestedSource).find('a.something').first().text();
This works for me in a very simple test on jsfiddle.
Note that you may have to play around with whatever $.find() returns if you have more than one anchor element with the class "something" (I just used $.first() to simplify my example). In that case, you can iterate through the results of $.find() like an array.
If that solution doesn't work, another (but worse) way you could do it would be to write the requested code to a hidden div, and then run $.find() from the div (though if the first solution doesn't work, there is likely something going wrong with request.source itself, so check its contents).
For example:
$('body').append('<div id="requestedSource" style="display: none;"></div>');
And then:
$("#requestedSource").append(request.source);
$("#requestedSource").find("a.something").first().text();
If you're repeating this request often, you can also empty the hidden div by calling $.empty() on it when you're done processing:
$("#requestedSource").empty();
For best performance, you would want to store everything in a variable and write once:
var hiddenRequestSource = '<div id="requestedSource" style="display: none;">';
hiddenRequestSource += request.source;
hiddenRequestSource += '</div>';
$('body').append(hiddenRequestSource);
var myResults = $("#requestedSource").find("a.something").first().text();
$("#requestedSource").empty();

Related

show all the values with .html [duplicate]

Lets say I have an empty div:
<div id='myDiv'></div>
Is this:
$('#myDiv').html("<div id='mySecondDiv'></div>");
The same as:
var mySecondDiv=$("<div id='mySecondDiv'></div>");
$('#myDiv').append(mySecondDiv);
Whenever you pass a string of HTML to any of jQuery's methods, this is what happens:
A temporary element is created, let's call it x. x's innerHTML is set to the string of HTML that you've passed. Then jQuery will transfer each of the produced nodes (that is, x's childNodes) over to a newly created document fragment, which it will then cache for next time. It will then return the fragment's childNodes as a fresh DOM collection.
Note that it's actually a lot more complicated than that, as jQuery does a bunch of cross-browser checks and various other optimisations. E.g. if you pass just <div></div> to jQuery(), jQuery will take a shortcut and simply do document.createElement('div').
EDIT: To see the sheer quantity of checks that jQuery performs, have a look here, here and here.
innerHTML is generally the faster approach, although don't let that govern what you do all the time. jQuery's approach isn't quite as simple as element.innerHTML = ... -- as I mentioned, there are a bunch of checks and optimisations occurring.
The correct technique depends heavily on the situation. If you want to create a large number of identical elements, then the last thing you want to do is create a massive loop, creating a new jQuery object on every iteration. E.g. the quickest way to create 100 divs with jQuery:
jQuery(Array(101).join('<div></div>'));
There are also issues of readability and maintenance to take into account.
This:
$('<div id="' + someID + '" class="foobar">' + content + '</div>');
... is a lot harder to maintain than this:
$('<div/>', {
id: someID,
className: 'foobar',
html: content
});
They are not the same. The first one replaces the HTML without creating another jQuery object first. The second creates an additional jQuery wrapper for the second div, then appends it to the first.
One jQuery Wrapper (per example):
$("#myDiv").html('<div id="mySecondDiv"></div>');
$("#myDiv").append('<div id="mySecondDiv"></div>');
Two jQuery Wrappers (per example):
var mySecondDiv=$('<div id="mySecondDiv"></div>');
$('#myDiv').html(mySecondDiv);
var mySecondDiv=$('<div id="mySecondDiv"></div>');
$('#myDiv').append(mySecondDiv);
You have a few different use cases going on. If you want to replace the content, .html is a great call since its the equivalent of innerHTML = "...". However, if you just want to append content, the extra $() wrapper set is unneeded.
Only use two wrappers if you need to manipulate the added div later on. Even in that case, you still might only need to use one:
var mySecondDiv = $("<div id='mySecondDiv'></div>").appendTo("#myDiv");
// other code here
mySecondDiv.hide();
if by .add you mean .append, then the result is the same if #myDiv is empty.
is the performance the same? dont know.
.html(x) ends up doing the same thing as .empty().append(x)
Well, .html() uses .innerHTML which is faster than DOM creation.
.html() will replace everything.
.append() will just append at the end.
You can get the second method to achieve the same effect by:
var mySecondDiv = $('<div></div>');
$(mySecondDiv).find('div').attr('id', 'mySecondDiv');
$('#myDiv').append(mySecondDiv);
Luca mentioned that html() just inserts hte HTML which results in faster performance.
In some occassions though, you would opt for the second option, consider:
// Clumsy string concat, error prone
$('#myDiv').html("<div style='width:'" + myWidth + "'px'>Lorem ipsum</div>");
// Isn't this a lot cleaner? (though longer)
var newDiv = $('<div></div>');
$(newDiv).find('div').css('width', myWidth);
$('#myDiv').append(newDiv);
Other than the given answers, in the case that you have something like this:
<div id="test">
<input type="file" name="file0" onchange="changed()">
</div>
<script type="text/javascript">
var isAllowed = true;
function changed()
{
if (isAllowed)
{
var tmpHTML = $('#test').html();
tmpHTML += "<input type=\"file\" name=\"file1\" onchange=\"changed()\">";
$('#test').html(tmpHTML);
isAllowed = false;
}
}
</script>
meaning that you want to automatically add one more file upload if any files were uploaded, the mentioned code will not work, because after the file is uploaded, the first file-upload element will be recreated and therefore the uploaded file will be wiped from it. You should use .append() instead:
function changed()
{
if (isAllowed)
{
var tmpHTML = "<input type=\"file\" name=\"file1\" onchange=\"changed()\">";
$('#test').append(tmpHTML);
isAllowed = false;
}
}
This has happened to me . Jquery version : 3.3.
If you are looping through a list of objects, and want to add each object as a child of some parent dom element, then .html and .append will behave very different. .html will end up adding only the last object to the parent element, whereas .append will add all the list objects as children of the parent element.

how to use html script template correctly

I have to generate some li element automatically and the way I was doing it it through a function that return text inside a loop, something like this:
function getLi(data) {
return '<li>' + data + '</li>';
}
then I found a better way to do it by writing html inside a div:
<div style="display:none;" id="Template">
<li id="value"></li>
</div>
and then I would change the id and value get the html and reset the element to original state:
var element = $("#value");
element.html(data);
element.attr('id', getNewId());
var htmlText = $("#Template").html();
element.html('');
element.attr('id', 'value');
return htmlText;
then I was reading on script template
and I figured this could be a better way of doing it,
However apply the previous code didn't work as the inner elements didn't exist according to this article
so how can I apply this?
EDIT:
I put inside a ul tag, I use this method to get the items dynamically
EDIT2:
<li>
<a href="#" >
<span>
<span>
some text
</span>
</span>
</li>
this isn't necessarily what I have but something along the way
Edit3:
my ul does not exist orgialy it's generated dynamically
I insist this is not a duplicate I want to know how to use a template with some dynamic variables
You could do the following way. It's clean, reusable and readable.
//A function that would return an item object
function buildItem(content, id) {
return $("<li/>", {
id: id,
html: content
});
}
In your loop, you could do the following. Do not append each LI inside the loop as DOM manipulation is costly. Hence, generate each item and stack up an object like below.
var $items = $();
// loop begin
var contents = ['<span><span>', data, '</span></span>'].join('');
var $item = buildItem(contents, getNewId());
$items.add($item);
// loop end
Just outside the loop. append those generated LIs to the desired UL, like below.
$("ul").append($items);
This is what I'd do and I am sure there are many better ways. Hope that helps.
One option is to upgrade to a modern JavaScript framework like AngularJS and then you could do it in one line using ng-repeat.
This would serve your purpose and make you more money as a developer.
If you're going to repeat this, use a templating system. Like {{ mustache }} or Handlebars.js.
If not, you can do this.
<ul>
<li class="hidden"></li>
</ul>
And in Javascript
$('ul .hidden').clone().removeClass('hidden').appendTo('ul');
And CSS, of course
.hidden { display:none }
Try this...
function getLi(data,ID) {
return $('<li id = "'+ ID + '">' + data + '</li>');
}
It returns javascript objest of Li..and you append it where ever you need.
what you need is using jquery templates, in the bellow link you can use good one which I'm using.
you create your template and prepare you JASON object of data.
after that every thing will be ready in one function call, more details in this link.
jquery.tmpl
hope this helps you and any one come to here in future..

How do I dynamically append a large block of HTML to a div?

I'm trying to learn web development, so I don't have much experience with the various languages and markups yet. I'm making a website with a blog that reads JSON data from the Tumblr v2 API. After getting the JSON data from Tumblr I want to add some of the data from each post to my own website's blog, here's the code that I've been trying to use..
<script>
function loadBlogPosts(){
$.getJSON("http://api.tumblr.com/v2/blog/[MY_BLOG]/info?api_key=[MY_KEY]",
function(blogData){
$.each(blogData.posts, function(){
$(#main_content).append( [BUNCH OF NESTED HTML] );
});
}
);
}
</script>
Before writing this, I thought it would be a good idea to make a 'layout' of each blog post in divs. So i came up with this:
<div class="post">
<div class="post_header">
<div class="post_title"></div>
<div class="post_author"></div>
<div class="post_date"></div>
</div>
<div class="post_content"></div>
<div class="post_footer"></div>
</div>
But that's where I'm stuck. I know what I want to do, but I don't have enough experience with JavaScript/JQuery/JSON/HTML to know how to do it. I want parse the JSON blog data and, for each post, take the post content and apply it to that div structure while writing/appending it to the "main_content" div.. I tried copy-pasting that group of divs into the append function surrounded by quotes, but it became a real mess of quotes and slashes, and it didn't look like it was working correctly..
So, whats the best way for me to do that? Is there a good way of applying a big chunk of nested HTML elements while populating them with content from my JSON data? If not, what should I do? I'm still very new to HTML, JavaScript, and web coding in general, so I may be going about this completely wrong!
If you want HIGH PERFORMANCE:
In pure javascript the highest performing method is probably using createDocumentFragment()
function postEl(json){ // create a function for the POST element
var post=document.createElement('div');
post.className='post';
var postHeader=document.createElement('div');
postHeader.className='post_header';
var postTitle=document.createElement('div');
postTitle.className='post_title';
postTitle.tectContent=json.title;
//more code
postHeader.appendChild(postTitle);
//more code
post.appendChild(postHeader);
return post;
}
function appendPosts(){ // append each post to a fragment. and then to the main
var frag=document.createDocumentFragment();
for(/*each post*/){
frag.appendChild(postEl(/*jsonPost*/));
}
document.getElementById('main_content').appendChild(frag);
}
Precreating the structure should also increase the performance.
cloneNode
https://developer.mozilla.org/en-US/docs/Web/API/Node.cloneNode
https://developer.mozilla.org/en-US/docs/Web/API/document.createDocumentFragment
cloning the node also increases the performance by setting the valuse directly without recreating each individual node.
function appendPosts(js){
var node=document.createElemtnt('div'),
frag=document.createDocumentFragment();
node.innerHTML='<div class="post_header"><div class="post_title"></div><div class="post_author"></div><div class="post_date"></div></div><div class="post_content"></div><div class="post_footer"></div>';
for(var a=0,b;b=js.posts[a];++a){
var newNode=node.cloneNode(true),
childs=newNode.childNodes,
header=childs[0].childNodes;
header[0].textContent=b.title/*title from Postdata*/;
header[1].textContent=b.author/*author from Postdata*/;
header[2].textContent=b.date/*date from Postdata*/;
childs[1].textContent=b.content/*content from Postdata*/;
childs[2].textContent=b.footer/*footer from Postdata*/;
frag.appendChild(newNode);
}
document.getElementById('main_content').appendChild(frag);
}
function loadBlogPosts(){
$.getJSON("http://api.tumblr.com/v2/blog/[MY_BLOG]/info?api_key=[MY_KEY]",
appendPosts
)
This function should work now .. but as i don't exactly know the json response you may need to change the various post keys.
note: i put the fragment thing in a function so you have an idea how it works.
you should put the postEl content inside the appendPosts function... (thats also faster)
if you have any questions just ask.
EDIT
no they are not globals
var a,b,c,d; // not globals == var a;var b;var c;var d;
var a,b;c;d; // c d = gobal
// , comma affter a var allows you to not write 1000 times var.
EDIT2
//.......
frag.appendChild(newNode);
}
var topNode=document.createElement('div');
topNode.className='post';
topNode.appendChild(frag);
document.getElementById('main_content').appendChild(topNode);
//.....
when you want to do everything with jquery yoiu could use something like this:
var post = $('<div class="post"></div>');
var postheader = $('<div class="post_header"></div>');
postheader.append('<div class="post_title"></div>');
postheader.append('<div class="post_author"></div>');
post.append(postheader);
post.append('<div class="post_content"></div>');
post.find('.post_title').text('my title');
post.find('.post_content').text('my content');
$('#main_content').append(post);
instead of .text('my title') you can use .text(variable) of course
Write your code in a separate page, then append a whole html page into a div by using:
$('#containerDiv').load('page.htm');
Also, this is a good way to fragment the content.
you could do something like this:
$.each(blogData.posts, function(i,v){
var cnt= '<div class="post">' +
'<div class="post_header">' +
'<div class="post_title">'+ blogData.posts[i].title +'</div>' +
'<div class="post_author">'+ blogData.posts[i].author +'</div>' +
'<div class="post_date">'+ blogData.posts[i].date +'</div>' +
'</div>' +
'<div class="post_content">' +
blogData.posts[i].body +
'</div>' +
'<div class="post_footer">' +
'</div>' +
'</div>';
$('#main_content').append(cnt);
});
Note that you don't need to split up all the lines, i've just done that to make it more readable. (I'm also not sure if all the variables are correct, (i don't think author exists) but it's just as a demo)

Counting classes on another page and displaying them

To save me a lot of work editing a number in when adding a document to a site I decided to use javascript to count the number of elements with a class doc .
I am two main problems:
There is trouble displaying the variable. I initially thought this was because I hadn't added function, however when I tried adding this the variable was still not displayed.
The elements with the class I want to count are on another page and I have no idea how to link to it. For this I have tried var x = $('URL: /*pageURL*/ .doc').length; which hasn't worked.
Essentially I want the total elements with said class name and this to be displayed in a span element.
Currently I have something similar to what's displayed below:
<script>
var Items = $('.doc').length;
document.getElementById("display").innerHTML=Items;
</script>
<span id="display"></span>
Found an example of something similar here where the total numbers of articles are displayed.
Edit:
#ian
This code will be added to the homepage, domain.net/home.html. I want to link to the page containing this documents, domain.net/documents.html. I've seen this done somewhere before and if I remember correctly they used url:domainname.com/count somewhere in their code. Hope this helps.
Here is a jQuery call to retrieve the url "./" (this page) and parse the resulting data for all elements with class "lsep" "$('.lsep', data)". You should get back a number greater than 5 or so if you run this from within your debug console of your browser.
$.get("./", function(data, textStatus, jqXHR)
{
console.log("Instances of class: " + $('.lsep', data).length)
});
One important thing to remember is that you will run into issues if the URL your are trying to call is not in the same origin.
Here's an updated snippet of code to do what you're describing:
$(document).ready(
function ()
{
//var url = "/document.html" //this is what you'd have for url
//var container = $("#display"); //this is what you'd have for container
//var className = '.data'; //this is what you'd have for className
var url = "./"; //the document you want to parse
var container = $("#question-header"); //the container to update
var className = '.lsep'; //the class to search for
$.get(url, function (data, textStatus, jqXHR) {
$(container).html($(className, data).length);
});
}
);
If you run the above code from your browser's debug console it will replace the question header text of "Counting classes on another page and displaying them" with the count of instances the class name ".lsep" is used.
First, you have to wait until the document is ready before manipulating DOM elements, unless your code is placed after the definition of the elements you manipulate, wich is not the case in your example. You can pass a function to the $ and it will run it only when the document is ready.
$(function () {
//html() allows to set the innerHTML property of an element
$('#display').html($('.doc').length);
});
Now, if your elements belongs to another document, that obviously won't work. However, if you have used window.open to open another window wich holds the document that contains the .doc elements, you could put the above script in that page, and rely on window.opener to reference the span in the parent's window.
$('#display', opener.document.body).html($('.doc').length);
Another alternative would be to use ajax to access the content of the other page. Here, data will contain the HTML of the your_other_page.html document, wich you can then manipulate like a DOM structure using jQuery.
$.get('your_other_page.html', function(data) {
$('#display').html($('.doc', data).length);
});

.html() and .append() without jQuery

Can anyone tell me how can I use these two functions without using jQuery?
I am using a pre coded application that I cannot use jQuery in, and I need to take HTML from one div, and move it to another using JS.
You can replace
var content = $("#id").html();
with
var content = document.getElementById("id").innerHTML;
and
$("#id").append(element);
with
document.getElementById("id").appendChild(element);
.html(new_html) can be replaced by .innerHTML=new_html
.html() can be replaced by .innerHTML
.append() method has 3 modes:
Appending a jQuery element, which is irrelevant here.
Appending/Moving a dom element.
.append(elem) can be replaced by .appendChild(elem)
Appending an HTML code.
.append(new_html) can be replaced by .innerHTML+=new_html
Examples
var new_html = '<span class="caps">Moshi</span>';
var new_elem = document.createElement('div');
// .html(new_html)
new_elem.innerHTML = new_html;
// .append(html)
new_elem.innerHTML += ' ' + new_html;
// .append(element)
document.querySelector('body').appendChild(new_elem);
Notes
You cannot append <script> tags using innerHTML. You'll have to use appendChild.
If your page is strict xhtml, appending a non strict xhtml will trigger a script error that will break the code. In that case you would want to wrap it with try.
jQuery offers several other, less straightforward shortcuts such as prependTo/appendTo after/before and more.
To copy HTML from one div to another, just use the DOM.
function copyHtml(source, destination) {
var clone = source.ownerDocument === destination.ownerDocument
? source.cloneNode(true)
: destination.ownerDocument.importNode(source, true);
while (clone.firstChild) {
destination.appendChild(clone.firstChild);
}
}
For most apps, inSameDocument is always going to be true, so you can probably elide all the parts that function when it is false. If your app has multiple frames in the same domain interacting via JavaScript, you might want to keep it in.
If you want to replace HTML, you can do it by emptying the target and then copying into it:
function replaceHtml(source, destination) {
while (destination.firstChild) {
destination.removeChild(destination.firstChild);
}
copyHtml(source, destination);
}
Few years late to the party but anyway, here's a solution:
document.getElementById('your-element').innerHTML += "your appended text";
This works just fine for appending html to a dom element.
.html() and .append() are jQuery functions, so without using jQuery you'll probably want to look at document.getElementById("yourDiv").innerHTML
Javascript InnerHTML
Code:
<div id="from">sample text</div>
<div id="to"></div>
<script type="text/javascript">
var fromContent = document.getElementById("from").innerHTML;
document.getElementById("to").innerHTML = fromContent;
</script>

Categories

Resources