jQuery Editing innerHTML after selecting it with .html() - javascript

I am generating rows dynamically with PHP from DB, once it compiles the initial page code looks something like this:
Snippet
<div class="options" id="options">
<div class="left_wrap">
<ul>
<li class="col_id b-bottom"></li>
<li class="hazard_header"><h3>Hazard</h3></li>
<li class="hazard_input b-bottom"></li>
<li class="con_header b-bottom"><h3>Controls</h3></li>
<li class="cat_header"><h3>Consequence Category</h3></li>
<li class="cat_options"></li>
</ul>
</div>
<div class="right_wrap">
<h2>Inherent Risk (Assessed risk without controls)</h2>
<ul class="fields">
<li class="bg b-top b-right"><h3>Consequence Level</h3><br/><span class="con_level_val"></span></li>
<li class="b-top b-right"><h3>Probability</h3><br/>Possible</li>
<li class="bg b-top b-right"><h3>Exposure (frequency)</h3><br/></li>
After page load I grab contents of the wrap options.
jQuery Snippet:
content = $("div.options").html();
Which in turns stores the above code in the variable content. Now, my question is how can I edit contents of variable content. For example I need to add value to li with class Col_ID like 1,2,3,4 and same when I am deleting I need to modify the contents again.
How can I do something along the lines content.getElement?

If you really need to work with the HTML string, here's something you can do:
content = $("div.options").html();
var $content = $(content);
// now $content is a jQuery object with a bunch of (detached) elements
// you can use the common functions on it without problems, such as
$content.find("li.col_id").text("Some text");
// now you need to do something with $content, or everything you did will...
// ...be lost. You cold, for instance, update the other variable back:
content = $content.html();
// content now has the updated HTML
Now, if you don't need the HTML string at all, then you can work directly like:
content = $("div.options");
content.find("li.col_id").text("Some text");
// now the DOM was already updated as you are dealing with attached elements

Related

How to add an image to a locked html code

I'm having a big problem here. I want to add an image to html code. No big deal if only I had access to the html code. Unfortunately it's locked and it looks like that:
<ul class="cc-nav-level-0 j-nav-level-0">
<li id="cc-nav-view-1691317785" class="jmd-nav__list-item-0 j-nav-has-children cc-nav-parent j-nav-parent jmd-nav__item--parent">
Sound Packs
<span data-navi-toggle="cc-nav-view-1691317785" class="jmd-nav__toggle-button"></span>
</li>
<li id="cc-nav-view-1691317885" class="jmd-nav__list-item-0">
Apps
</li>
<li id="cc-nav-view-1691318285" class="jmd-nav__list-item-0">
Comments
</li>
<li id="cc-nav-view-1701055985" class="jmd-nav__list-item-0">
News
</li>
</ul>
The image I would like to add should be to the right of the font. Is there a way to insert the code somehow?
Sure, you should be able to do what you want. Look at the jQuery commands: .append(), .html(), etc. For example:
Note that you can also inject new CSS the same way...
$(function(){
var newstuff = '\
<style>\
#new{color:red;}\
</style>\
<div id="new">Here is a newly-injected DIV</div>\
';
$('#mt').html(newstuff);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>
<div id="mt">You can replace what is there with modified/enhanced code.</div>
You could try to link a script that inserts an element after the DOM loads. Something like this:
document.addEventListener('DOMContentLoaded', () => {
document.querySelector('ul').insertAdjacentHTML('afterend', '<div></div>')
})
Then you could use inline styling to make it whatever height, width and background you'd like:
<div style="height:300px;width:300px;background:url(yourImg.jpg);></div>
I made a quick pen to show you what it looks like.

Using jquery load() to add content into tabbed navigation

I have a web application that uses tabbed navigation from a UI kit: http://www.getuikit.com/docs/tab.html.
Each tab will load different content, which is broken down into several php scripts, one per tab.
One (not very efficient, but so for successful) option is to load up all of the tabs content when the page first loads, so to use the standard example:
<!-- This is the container of the toggling elements -->
<ul data-uk-switcher="{connect:'#my-id'}">
<li><a id="1" class="load-tab" href="">Tab 1</a></li>
<li><a id="2" class="load-tab" href="">Tab 2</a></li>
</ul>
<!-- This is the container of the content items -->
<ul id="my-id" class="uk-switcher">
<li><?php require('script1.php'); ?></li>
<li><?php require('script2.php'); ?></li>
</ul>
I want to avoid this though, because the scripts are quite hefty so want to load them on demand for better user experience.
So what I've done is instead add holding divs and target them with a jQuery load():
<!-- This is the container of the content items -->
<ul id="my-id" class="uk-switcher">
<li><div id="1"></div></li>
<li><div id="2"></div></li>
</ul>
jq:
$(document).on("click", "a.load-tab", function(){
//get the value of the tab clicked in the nav
var tab = $(this).attr('id');
//determine the filename to load based on tab clicked
if (tab == '1'){ var filename = 'script1.php'; }
if (tab == '2'){ var filename = 'script2.php'; }
//load it
$( "#"+tab+ ).load( filename );
});
This works fine ... ish.
Question is this: With the initial (non jquery) method, each script could use the main page's core files that have already been included, e.g. header.php, functions.php etc etc. But when the content is loaded from jquery it seems each script needs to be included in the scipt1.php file and loaded again, which results in duplicate content being created in the DOM.
EDIT
script1.php currently is structured something like:
<?php
require('header.php');
require('connect.php');
require('setUser.php');
require('setParams.php');
require('functions.php');
?>
<div id="header">
//header content
</div>
<table>
//table content
</table>
The page that the navigation sits within, let's just call it index.php for now, already must have those php files included, so you can see the duplication issue.
What can be done to avoid this? Thought of a few options like iframes but seems like it might be a hack.
Your issue is essentially inside 'script1.php' you have something that requires 'connect.php' / data that is populated. But you are doubling up on DOM elements when you pull that in.
Two solutions to that issue are: 1 - create slimmer versions of your lib php files that don't include any DOM elements, only the data required to populate script1.php's data, or
script1.php contains
<?php
require('header.php');
require('connect.php');
require('setUser.php');
require('setParams.php');
require('functions.php');
?>
<div id="header">
//header content
</div>
//Everything inside #content is what you want to pull in
<div id="content">
<table>
//table content
</table>
</div>
And then call
$("#1").load("script1.php #content");
This will only load the HTML that is inside the #content div.

Parsing structure/hierarchy of html and recreating it in a different form with javascript

I am trying to crawl some webpages with javascript to gather information about content's hierarchy. I'm using casperjs to do the crawling, that is working ok so far.
The information that I want to parse is structured like this:
<ul>
<a></a>
<li>
<h3>
<a>
Category
<span>Description for Category</span>
</a>
</h3>
<div>
<ul>
<li>
<a>SubCategory</a>
</li>
</ul>
</div>
</li>
</ul>
But what I want to end up with is this.
<ul>
<li>Category
<ul>
<li>SubCategory</li>
</ul>
</li>
</ul>
I want to use the above html in a different webpage, so basically I'll be writing it to a file from casperjs so that I can then copy paste it into another document. I'm crawling because it's a tedious thing to do manually (90 some pages and lots of data per page).
What's the best way to deconstruct/parse a hierarchy, and then recreate it? Stay within the DOM and restructure using JQuery? Pull it out into a tree structure and rebuild it later?
Please note that this is a particular solution and will only work for the specific layout of code that you provided:
I created a parser in jQuery that receives HTML markup in a textarea and converts it into the format that you are using:
$(function(){
$("button").click(function(){
//Read in HTML
$("#parser").html($("textarea").val());
//Parse
var categories = $("#parser > ul").find("li h3 a");
$(categories).find("span").remove();
//Output result
var output = "<ul>\n";
for(var i = 0; i < categories.length; i++)
{
//Get subcategories for this category
var subCategories = $($(categories[i])).closest("h3").siblings("div").find("ul li a");
//Add markup to output
output += "\t<li>" + minimize($($(categories[i])).html()) + "\n\t\t<ul>\n";
for(var j = 0; j < subCategories.length; j++)
{
output += "\t\t\t<li>"+$($(subCategories[j])).html() + "&lt/li>\n"
}
output += "\t\t</ul>\n\t</li>\n</ul>\n"
}
$("#result").html(output);
});
});
//Removes all white-space characters from the string.
function minimize(str)
{
return str.replace(/\s{2,}/g, '');
}
JSFiddle
It was a lot of work and is very customized. As I said earlier, if you look at the different selectors that are used here, this code is very tailored to this specific code layout.
Example:
var categories = $("#parser > ul").find("li h3 a");
This looks for a ul element just below parser that contains <a>s inside of <h3>s inside of <li>s to find the categories and then later uses
$($(categories[i])).closest("h3").siblings("div").find("ul li a");
which looks for an <h3> above the category <a> that has a sibling <div> with children <ul><li><a></a></li></ul>
So if the format is not this:
<ul>
<li>
<h3>
<a>Category</a>
</h3>
<div>
<ul>
<li>
<a>Subcategory</a>
</li>
</ul>
</div>
</li>
</ul>
It will not work.
I ended up going with this approach:
Scrape the tags from the existing website and assemble them into an array nested javascript object.
Writing them out with JSON.stringify to a file
Loading them into a new page as Javascript objects, and build the ul/li structure with a recursive function that traversed the javascript object.
I found it too hard to get my head around modifying the DOM as with the other answer(s). It was easier to break it down into multiple steps, with a well structured javascript object in the middle.

Inserting HTML into tag using JavaScript

I'm having a problem with JavaScript/jQuery at the moment where I'm trying to access the element inside the h4 element in my code. I'm doing this because I would like to dynamically display to the user how many guides are available in each "h4" section. For the PC section, it should display "4 reviews available" and for the Xbox One section, it should display "3 reviews available". However, both say " reviews available", and I'm assuming it's because I'm not using the jQuery functions properly. Here's the HTML code:
<h4><li class="console">PC (<span class="number"></span> reviews available)</li></h4>
<div class="gameList">
<ul>
<li class="game">Guide #1</li>
<li class="game">Guide #2</li>
<li class="game">Guide #3</li>
<li class="game">Guide #4</li>
</ul>
</div>
<h4><li class="console">Xbox One (<span class="number"></span> reviews available)</li></h4>
<div class="gameList">
<ul>
<li class="game">Guide #1</li>
<li class="game">Guide #2</li>
<li class="game">Guide #3</li>
</ul>
</div>
And here's the jQuery/JavaScript code:
$("h4").each(function() {
var node = $(this).children().children(); // gets node that has "number" class
var count = $(this).next().children().children().length; // gets number of li tags
node.innerHTML = count;
});
I tested whether or not it's properly getting the correct node and count by using the alert function for JavaScript, but for some reason, node.innerHTML = count won't display the contents of "content" properly in the element. Rather, it just displays a blank. Does anyone know why?
Its a jquery object not a DOM one..use this...
node.html(count);
node is a jQuery object here. It does not have "innerHTML". Instead you can use one of these:
node.html(count);
node.get(0).innerHTML = count;
node.get(0) will give you first DOM object from jQuery one.
A good practice is to prefix or suffix all jQuery objects with $ (e.g. $node), so that you will always know if a variable is meant to be a jQuery object.
use find() lot more cleaner and readable
$("h4").each(function() {
var $this=$(this);
var node = $this.find('.number');
var count = $this.next().find('li').length; // gets number of li tags
node.text(count); //or html()
});
and you have come invalid HTML li in h4 make sure you change that
working fiddle here
Do not use .children().children().
Only one .children() would do.
$(this).children('.game');
Also innerHTML is plain javascript. use .html(value) as node is JQuery Object.
$("h4").each(function() {
var node = $(this).children('.number');
var count = $(this).next().children('li').length;
node.html(count);
});
Reference to JQuery APIs:
.html()
.children()
$("h4").each(function() {
var $spanNumber = $('.console .number', this),
gameListCount = $(this).next().find('ul li').size();
$spanNumber.text(gameListCount)
});
You may use this also,
$("h4").each(function() {
var node = $(this).find('.number');
var count = $(this).next().find('.game').length;
node.html(count);
});

jquery load() specific div not working

Here is the portion of HTML in question as well Javascript related to it:
HTML first:
<div id="menu">
<ul>
<li>click</li>
</ul>
</div>
Javascript goes:
$("#menu a").click(function(){
var link=encodeURI($(this).attr("href"));
$("#divtobeloadedwith").load(link);
return false;
});
content.html structure:
<div id="wrapper">
<div id="diviwant">stuff</div>
<div id="dividontwant">stuff</div>
</div>
Upon clicking on link it loads all the content instead only specific div.
Fundamentally the problem is that you want two different things:
When running without Javascript, you want to use the link content.html#diviwant, as that will load the page content.html and then jump to the element with the ID diviwant.
When running with Javascript, you want to pass content.html #diviwant to jQuery's load() method, as that tells jQuery to load only the fragment with the id diviwant from the target page.
I'd probably use content.html#diviwant as the link, as you've got, then interpret that in the jQuery like this:
$("#divtobeloadedwith").load(link.replace('#', ' #'));
...to add the necessary space for the load().
You need to remove the space between content.html and #diviwant in the href of your link.
<li>click</li>
You also need to make sure that "divtobeloaded" exists.
<div id="menu">
<ul>
<li>click</li>
</ul>
</div>
<div id="divtobeloaded"></div>

Categories

Resources