How to import a JavaScript code to another html document? - javascript

how can I import JavaScript document where defined some variables into a html document, so I can output these variables there?
I tried it that way but it didn´t work. I defined the variable title in my other script an gave it the Id title. The name of the file is server.js, so I worte in the html document this as the source but it doesn´t work. The data cell where I want to output it is empty. When I define the variable in the same document it works but not when i do it in the server.js document.
<body>
<script src="server.js"></script>
<table>
<tr>
<th>header</th>
</tr>
<tr>
<td> <div id="title"> </td>
</tr>
</table>
</body>
the part from my second script:
let title = $("#productTitle").text().replace(/\s\s+/g, "");
document.getElementById("title").innerHTML= title;

The answer is simple. Just import the javascript file outside of the body tag. You are not getting the desired result because the JavaScript is loading before the remaining body elements and it is not able to find the desired element with id title.
Before putting the script tag just after </body> just open the browser console you will see an error like this: Uncaught TypeError: Cannot set properties of null (setting 'innerHTML').
So the new code should be like
<body>
<table>
<tr>
<th>header</th>
</tr>
<tr>
<td> <div id="title"> </td>
</tr>
</table>
</body>
<script src="stack.js"></script>

Related

Nested StimulusJS scopes / controller issue / HTML 5 template tag

I have a basic Rails app with a nested association and I am doing a standard 'line items' type view where I am dynamically adding and removing rows from a template tag. I have a select that triggers a AJAX call to replace all the nested row selects (the context changed). The expenditure controller handles the overall form and the nested-form controller is used on other pages to handle the adding and removal of rows:
<div data-controller="expenditure nested-form">
<select data-target="expenditure.budget" data-action="change->expenditure#update_related"></select>
<table>
<thead></thead>
<tbody>
inserted rows...
<tr>
<td>
<select data-target="expenditure.budgetItemSelect"></select>
</td>
</tr>
<template data-target="nested-form.template">
<tr data-new_record="true">
<td>
<select data-target="expenditure.budgetItemSelect"></select>
</td>
</tr>
</template>
</tbody>
</table>
</div>
It works fine. I can add and remove rows and if I change the expenditure.budget select all the expenditure.budgetItemSelect targets get updated EXCEPT for the one inside the template. It's as if it's missing from the entire scope of the controller. I had them nested before but now have them in the same div data-controller="expenditure nested-form" to double check and it still doesn't work. Checked spelling and even tried removing the data-target="nested-form.template". No errors in the browser console. Am I missing something obvious here?
UPDATE
Hmmm... it seems that the template tag is read only and NOT part of the DOM which is why this fails.
I managed a hack where I replaced the contents of the entire template but that seems to break the controller that adds / deletes the rows 🤦‍♂️.
UPDATE 2
I found a workaround - If someone can improve this code I will accept this as a better answer.
It seems to be an issue with the <template> tag in HTML5.
I have a workaround but it's ugly.
<div data-controller="expenditure nested-form">
<select data-target="expenditure.budget" data-action="change->expenditure#update_related"></select>
<table>
<thead></thead>
<tbody>
inserted rows...
<tr>
<td>
<select data-target="expenditure.budgetItemSelect"></select>
</td>
</tr>
<template id="expenditure_items_template">
<tr data-new_record="true">
<td>
<select data-target="expenditure.budgetItemSelect"></select>
</td>
</tr>
</template>
<script type="text/template" data-target="nested-form.template" id="expenditure_items_template_script">
</script>
</tbody>
</table>
</div>
Here is what I did in my controller:
// find the template
var template = document.getElementById("expenditure_items_template");
// load the template contents
var new_template = document.importNode(template.content, true);
// replace the select with my new content (off screen)
new_template.getElementById('expenditure_expenditure_items_attributes_NEW_RECORD_budget_item_id').innerHTML = select.innerHTML;
// clear the new script place holder
document.getElementById("expenditure_items_template_script").innerHTML = "";
// set the new updated template into the script tag
document.getElementById("expenditure_items_template_script").appendChild(new_template);
I basically have two templates - one <template> which holds the raw HTML and the second <script> that works with Stimulus.

How to get element content in table but outside tr tag in jQuery?

Data I received from database, Postgresql, is html content for rendering in browser, it is as following:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Employee</title>
</head>
<body>
<table>
<tr>
<td>ID</td>
<td>First Name</td>
<td>Last Name</td>
</tr>
<tr>
<td>CU0012</td>
<td>David</td>
<td>Jonh</td>
</tr>
untitle Name <!-- content I would like retrieve and manipulate -->
<tr>
<td>CU0010</td>
<td>Siv</td>
<td>Hellen</td>
></tr>
<tr>
<td>CU0009</td>
<td>Merry</td>
<td>Mug</td>
></tr>
</table>
</body>
</html>
Is it possible that I want to be able to get text untitle Name that is in table but outside of tr tag so that I can manipulate it thereafter?
As a mater of fact, after this html script rendered in browser, any content that is not wrap properly in table would be forced to get outside of table, yet before it rendering I would like to keep there by access to it and make it properly wrap into table.
<script>
$(document).ready(function(){
htmlTable = $('table tr').html();
htmlTable.each(function(){
// check element is in tr or not
});
})
</script>
How can I archive that in jQuery? Thanks.
When receive html content by ajax or other method, you can use String.prototype.replace() to remove the unexpected html content or replace with expected content before load it into one html element.
//for example, you receive below text from the server
var serverData = '<table border="1"><tr><td>CU0012</td><td>David</td><td>Jonh</td></tr>untitle name<tr><td>CU0010</td><td>Siv</td><td>Hellen</td></tr></table>';
function loadReviseHtml(){
var reviseData = serverData.replace(/<\/tr>\s*(.+)\s*<tr>/, '</tr><tr><td style="background-color:red">$1</td></tr><tr>');
console.log(reviseData)
document.getElementById('htmlcontainer1').innerHTML = reviseData;
}
function loadOrgHtml(){
document.getElementById('htmlcontainer1').innerHTML = serverData;
}
<a onclick="loadReviseHtml()" style="background-color:green;">Click me to load revised html!</a>
<div id="htmlcontainer1" style="background-color:gray;">
No Data!
</div>
<a onclick="loadOrgHtml()" style="background-color:red;">Click me to load org html!</a>

Why doesn't .html() replace everything with current value?

Here is my code:
$('table').html('<tr><td>test</td></tr>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<img src="default.jpg" />
</table>
As you see, that image is still there. Why? I've used .html, so this is expected result after executing this: $('table').html('<tr><td>test</td></tr>');
<table>
<tr>
<td>test</td>
</tr>
</table>
How can I do that?
The reason is that the img isn't inside the table as of when you call html, because it's not allowed to be. <table><img ...></table> is invalid markup; tables can only directly contain certain table-related elements, not img elements. So the browser fixes it for you by moving the img out of the table. (For instance: Chrome fixes it by moving the img to just in front of the table: <img ...><table></table>.)
If it were in the table in the first place, yes, calling html to replace the table contents would work:
$('table').html('<tr><td>test</td></tr>');
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<tr>
<td>
<img src="default.jpg" />
</td>
</tr>
</table>
In a comment you've asked:
...how can I select the image in this? <img src="#" /> <table></table> ? Actually I want to start selecting with table tag. like this $('table').sibiling ...
I don't think you can, reliably, because again the original markup was invalid and so browsers are free to do what they want to handle it. That said, Chrome, Firefox, and IE11 all seem to put the img before the table, so $("selector-for-the-table").prev() should be the img:
var table = $('table');
table.html('<tr><td>test</td></tr>');
table.prev().remove(); // Remove the img
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<table>
<img src="default.jpg" />
</table>
IMG is not a text tag. If you want to hide it, you must remove it.

Cant sort html table using sorttable.js

Im having trouble trying to sort a dynamically created html table. I create it using jade/pug. I am trying to use the sorttable.js script found here http://www.kryogenix.org/code/browser/sorttable/ . I am still kind of new to html/javascript. So if there is some obvious reason why its not working could someone point it out please?
Here is some of the html code generated from the template
<html>
<head>
<script src="/path/to/sorttable.js"></script>
<style>
th.clickable:hover
{
color:green
}
th, td
{
padding:5px;
}
th.clickable
{
cursor: pointer;
}
</style>
</head>
<body>
<script>
var newTableObject = document.getElementById(tbl)
sorttable.makeSortable(newTableObject)
</script>
<table class="sortable" id="tbl">
<tr>
<th class="clickable">id</th>
<th class="clickable">value</th>
</tr>
<tr>
<td>100</td>
<td>100</td>
</tr>
<tr>
<td>200</td>
<td>200</td>
</tr>
</table>
</body>
</html>
The goal is to have it so when I click on the header it sorts the table by that column.
Please excuse if this is already known...but
The script tag gets read and executed whenever the browser comes across it. Have you tried putting the script tag after your table?
At the time your code executes:
var newTableObject = document.getElementById(tbl)
sorttable.makeSortable(newTableObject)
Your table hasn't rendered yet and is unavailable. So you;re passing undefined to the sorttable.makeSortable method. You can test this by adding a trace statement after you get the element:
var newTableObject = document.getElementById(tbl)
console.log(newTableObject)
You should wait to fire this code after your table has rendered. Something like this:
onLoad = function(){
var newTableObject = document.getElementById(tbl)
sorttable.makeSortable(newTableObject)
}
and declare that like so:
// using jQ
$(document).ready( onLoad())
or for plain JS
<body onload="onload()">

need help with arrays and links in javascript

Hi i have a question regarding html and javascript.
Say that i click on a link on a html site say
<tr>
<td>www.hello1.com</td>
</tr>
then I also want to see if there are any other related link on that site with a narrow name, for example
<tr>
<td>www.hello2.com</td>
</tr>
So what I want to do is construct a javascript method that everytime you click on a link
you run this method and check what link that has been pressed, and then also search the entire html site for a similar link (here its very simple, the site only consist of a table containing links, so there will not be so much to search trough).
How is this done?
I only need the method, I know how to run the method everytime you press a link :)
Thanks in advance :)
Edit
With "similar" i mean something like this
'\\b'+theUrlToGoTo+'\\b'
In other words the only thing that will change is a number after the name for example
hello1 and hello2
Edit 2
Thanks to nemophrost I now know how to do the first one. I now have a second question, before Im done, thats regarding generating html code with javascript.
Now say that I have an array after I have run the everyClickFunc() func that includes
var myArray = [ 'www.hello1.com', 'www.hello2.com', 'www.hello3.com'];
I would now like to generate a simple html page like this
<html>
<head>
</head>
<body>
<table>
<tr>
<td>www.hello1.com</td>
</tr>
<tr>
<td>www.hello2.com</td>
</tr>
<tr>
<td>www.hello3.com</td>
</tr>
</table>
</html>
And this file is to be overwritten each time I click on a link. So the links will be diffrent depending on what links i click on, on the original site.
In other words I want something like this
<html>
<head>
</head>
<body>
<table>
<tr>
<td>www.testing1.com</td>
</tr>
<tr>
<td>www.hello1.com</td>
</tr>
<tr>
<td>www.testing2.com</td>
</tr>
<tr>
<td>www.hello2.com</td>
</tr>
<tr>
<td>www.hello3.com</td>
</tr>
<tr>
<td>www.diffrent1.com</td>
</tr>
<tr>
<td>www.diffrent2.com</td>
</tr>
</table>
</html>
To generate a new html site that contains the following information if you click on any of the above "hello" links
<html>
<head>
</head>
<body>
<table>
<tr>
<td>www.hello1.com</td>
</tr>
<tr>
<td>www.hello2.com</td>
</tr>
<tr>
<td>www.hello3.com</td>
</tr>
</table>
</html>
How is this easiest solved?
Again thanks you so much in advance :)
With jQuery you could do something like this:
function everyClickFunc(urlToMatch) { // pass in something like 'www.hello1.com'
var baseURLMatch = urlToMatch.match(/^www\.(.+\D)\d*\.com$/);
if (baseURLMatch && baseURLMatch.length > 1) {
var matchExp = new RegExp('^www\\.' + baseURLMatch[1] + '\\d*\\.com$');
$('a').each(function() {
if ($(this).attr('href').match(matchExp)) {
doSomethingBecauseYouGotAMatch(); // Call your successful match function
}
});
}
}

Categories