jQuery append() not working on certain element - javascript

The website I'm creating is http://www.industrialmerchants.com
The problem portion of my script is the following:
var collapseAll = document.createElement('img');
collapseAll.src = collapseAllSrc;
collapseAll.className = "collapseAll";
collapseAll.style.cssFloat = "right";
imUI(".menuBrowser .sideModuleHeader").append(collapseAll);
(imUI is the noConflict variable I'm using. If you are wondering why I use this verbose method of creating a DOM element, it is because this was my last ditch effort to get this code to work.)
For some bizarre reason, nothing is appended to the selected div. The div is definitely being selected because the length property is returning 1. To make things even more confusing, I have another "module" with a nearly identical DOM structure. When I alter the selector to include the .sideModuleHeader div from both modules, the image is inserted in the second module but not the first. Any ideas?

It does get added, but a few lines later you have:
toggleButtons = imUI(".menuBrowser img").remove(".collapseAll")...
which then immediately deletes it.

Looks like you are mixing core javascript with jquery.
try:
var collapseAll = $('<img />').attr('src',collapseAllSrc).addClass("collapseAll");
collapseAll.css({'float':'right'})
-edit: i had a ':' instead of a ',' on the attr part.

Try with append Child:
imUI(".menuBrowser .sideModuleHeader").appendChild(collapseAll);

Related

How do I stop my dynamic content being appended to end of content?

I'm trying to write some JavaScript that once the page has finished loading will create a div in the place where the is placed.
Here is a stripped-back version of the code...
window.addEventListener('load', function () {
var content = document.createElement('div');
content.id = 'div-ID';
document.getElementsByTagName('body')[0].appendChild(content);
});
It works outside of the addEventListener(), however, when inside the event listener it always puts the created div below the rest of the page content not in the place the <script> tag is placed.
I'm certain the issue is to do with this line...
document.getElementsByTagName('body')[0].appendChild(content);
I need an alternative version to this which doesn't appendChild() but my JS isn't that good and everything I've tried hasn't worked.
Its most likely simple to achieve, I've tried searching Google and Stack Overflow but my search terms don't seem to be producing the desired results.
Any help on this would be much appreciated
You could do it with Node.insertBefore
As such, your code would be something like:
document.body.insertBefore( content, document.body.childNodes[0] );
The second parameter is the referenceNode, that has following comment:
referenceNode is not an optional parameter -- you must explicitly pass a Node or null. Failing to provide it or passing invalid values may behave differently in different browser versions.

Remove all elements from website except X

I'm not really familiar with Javascript, and even less with how Javascript works in Chrome's F12 developer tools. What I'm trying to do is have a favorite which, when clicked on, loads a web page but removes some of the clutter of the page which is loaded (I don't really care if it removes it before the page is loaded, or loads it and then removes it)
For now, I'm trying to figure out how to remove all elements except the one I want to keep (and its' children), namely, one which has the following html:
<div>
<ul class="c-list-news u-relative" data-load-more-content>...</ul>
</div>
I'm trying the following (from what I could find on SO), but I can't find the right selector (or I'm doing something else wrong, not quite sure):
var elem = document.querySelectorAll('body *:not(div ul.c-list-news, div ul.c-list-news *)');
for(var i=0;i<elem.length;i++) {
elem[i].parentElement.removeChild(elem[i]);
}
(PS : I haven't yet looked into how to put it into a favorite/extension, it will come later)
It's probably easier than you realize. :-) You can get the first element matching .c-list-news like this:
const cListNews = document.querySelector(".c-list-news");
If you want to keep its parent, just add .parentNode to that:
const divContainer = document.querySelector(".c-list-news").parentNode;
Then, wipe out body entirely:
document.body.innerHTML = "";
...and put the element back:
document.body.appendChild(cListNews); // Or `divContainer`
I'm not sure I'd expect the page to continue to be readable, though, since of course this completely changes where the element is in the DOM, which may well make the CSS fail.
You can't make a bookmark (favorite) that both loads the page and does this in one go, because javascript: bookmarks work within the context of the current page. You could use something like TamperMonkey which is an extension that lets you run a script automatically when you go to matching URLs.
But you can make a bookmark that you use when you're already on the page: Just use the javascript: pseudo-protocol and follow it with JavaScript code. For instance:
javascript:var divContainer %3D document.querySelector(".c-list-news").parentNode%3Bdocument.body.innerHTML %3D ""%3Bdocument.body.appendChild(divContainer)%3Bconsole.log("done")%3B
I created that by simply removing line breaks from the code (optional), running the code through encodeURIComponent, and putting javascript: on the front. (Some folks would also convert spaces to %20.)
Save the element to keep to a variable. Remove all nodes from the body, or the element that you want, and add the element to keep. Example:
let elementToKeep = document.getElementById('side');
const myNode = document.getElementsByTagName("body")[0];
while (myNode.firstChild) {
myNode.removeChild(myNode.firstChild);
}
myNode.appendChild(elementToKeep);
Using the removeChild method is faster that setting the innerHtml as empty string.
Check here: Remove all child elements of a DOM node in JavaScript

lightbox not working on new content

Hy, I'm having some problems making lightbox (in my case slimbox 2) work
after new content is loaded. I understand that slimbox needs to be called again, but I tried almost everything.
Here is the code how new content is been loaded:
...var link = $('<a class="loadpost" href="javascript:">Load more</a>');
link.click(loadMore);...
loadMore is the function that loads new content. this is just a piece of code. if you need the whole code let me know.
Here is the slimbox code.
jQuery(function($) {
$("a[rel^='lightbox']").slimbox({/* Put custom options here */}, null, function(el) {
return (this == el) || ((this.rel.length > 8) && (this.rel == el.rel));
});
the new content has the rel attributes but it wont work. can i combine the click function from above to call slimbox code again.
Long version:
Without more of the code (if you can, make a jsfiddle or something similar) it's hard to know if this is the only issue, but one immediate issue I'm seeing is that you're using jQuery's $(" ") wrong. You're supposed to put a selector in there, so that jQuery can find whatever it is you want it to find in the DOM; what you're feeding it is a string of HTML.
Browsers use HTML to make the DOM (Document Object Model) tree, which you can think of as an abstracted logic tree of your HTML; the DOM sees 'a.loadpost' as a parent of the text node inside of it (in this case, 'Load more'). CSS and Javascript/jQuery both find information from that abstracted logic tree in pretty similar ways. With a few exceptions, if you know how to target something with CSS, you know how to target it with jQuery -- just select whatever HTML you need to select the same way you would with CSS.
So, to tell jQuery to do something to a link with a class of 'loadpost', you simply write $('a.loadpost'). $("a.loadpost") works as well.
Short version:
var link = $('a.loadmore');

Only one node inside div - HTML, JavaScript

I have looked something different from .appendChild() and .innerHTML but to work with Image() JavaScript objects.
I have 10 variables, img[1,2,3,4...10], created with JavaScript (new Image()) to pre-load and it's OK, now I want to insert it into my div only one at time.
innerHTML returns something like HTMLImageObject and appendChild() won't work like I want.
My solution so far is:
document.getElementById("teste").removeChild(document.getElementById("teste").firstChild);
document.getElementById("teste").appendChild(img1);
Someone have any better ideas?
If you don't want appendChild use replaceChild. For example:
div.replaceChild(imgs[i], div.firstChild);
Demo: http://jsfiddle.net/8bKy8/
your way is pretty solid but maybe like this is easier to read.. also lastChild has a marginal performance advantage
var ele = document.getElementById('teste');
while(ele.lastChild) {
ele.removeChild(ele.lastChild)
}
ele.appendChild(img1);
http://jsperf.com/innerhtml-vs-removechild/15
you could also keep a reference to the element somewhere
var ele = document.getElementById('teste'), img = ele.lastChild;
ele.removeChild(img);
ele.append(img1);
if you have jQuery available you can use
$('#teste').clear().append(img1);
depending on the browser you are using you potentially also have access to the HTML5 Selector API as well even without jquery that may be an alternative to the document.element method
document.querySelector('#tests').first();
https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Locating_DOM_elements_using_selectors

Append html to jQuery element without running scripts inside the html

I have written some code that takes a string of html and cleans away any ugly HTML from it using jQuery (see an early prototype in this SO question). It works pretty well, but I stumbled on an issue:
When using .append() to wrap the html in a div, all script elements in the code are evaluated and run (see this SO answer for an explanation why this happens). I don't want this, I really just want them to be removed, but I can handle that later myself as long as they are not run.
I am using this code:
var wrapper = $('<div/>').append($(html));
I tried to do it this way instead:
var wrapper = $('<div>' + html + '</div>');
But that just brings forth the "Access denied" error in IE that the append() function fixes (see the answer I referenced above).
I think I might be able to rewrite my code to not require a wrapper around the html, but I am not sure, and I'd like to know if it is possible to append html without running scripts in it, anyway.
My questions:
How do I wrap a piece of unknown html
without running scripts inside it,
preferably removing them altogether?
Should I throw jQuery out the window
and do this with plain JavaScript and
DOM manipulation instead? Would that help?
What I am not trying to do:
I am not trying to put some kind of security layer on the client side. I am very much aware that it would be pointless.
Update: James' suggestion
James suggested that I should filter out the script elements, but look at these two examples (the original first and the James' suggestion):
jQuery("<p/>").append("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there")
keeps the text nodes but writes gnu!
jQuery("<p/>").append(jQuery("<br/>hello<script type='text/javascript'>console.log('gnu!'); </script>there").not('script'))`
Doesn't write gnu!, but also loses the text nodes.
Update 2:
James has updated his answer and I have accepted it. See my latest comment to his answer, though.
How about removing the scripts first?
var wrapper = $('<div/>').append($(html).not('script'));
Create the div container
Use plain JS to put html into div
Remove all script elements in the div
Assuming script elements in the html are not nested in other elements:
var wrapper = document.createElement('div');
wrapper.innerHTML = html;
$(wrapper).children().remove('script');
var wrapper = document.createElement('div');
wrapper.innerHTML = html;
$(wrapper).find('script').remove();
This works for the case where html is just text and where html has text outside any elements.
You should remove the script elements:
var wrapper = $('<div/>').append($(html).remove("script"));
Second attempt:
node-validator can be used in the browser:
https://github.com/chriso/node-validator
var str = sanitize(large_input_str).xss();
Alternatively, PHPJS has a strip_tags function (regex/evil based):
http://phpjs.org/functions/strip_tags:535
The scripts in the html kept executing for me with all the simple methods mentioned here, then I remembered jquery has a tool for this (since 1.8), jQuery.parseHTML. There's still a catch, according to the documentation events inside attributes(i.e. <img onerror>) will still run.
This is what I'm using:
var $dom = $($.parseHTML(d));
$dom will be a jquery object with the elements found

Categories

Resources