Need to put JS modules in correct order - javascript

I got a task to render a word using pure JavaScript and modules, but always got mistakes like params of renderDOM function is undefined and so on. I'm able to choose the order of scripts, use IIFE
here is html:
<!DOCTYPE HTML>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="root"></div>
<script src="invert.js"></script>
<script>
window.render.renderDOM('.root', reverse('sseccus'));
</script>
<script src="dom.js"></script>
</body>
</html>
and 3 files with functions:
dom.js
const TAG = 'div';
function createElement(tag = TAG, content) {
const element = document.createElement(tag);
element.textContent = content;
return element;
}
render.js
const TAG = 'p';
function renderDOM(selector, content) {
const root = document.querySelector(selector);
if (!root) {
return;
}
const element = createElement(TAG, content); // createElement из файла dom.js
root.appendChild(element);
}
reverse.js
(function () {
function reverse(str) {
return str.split('').reverse().join('');
}
})();
I've tried to add type='module', added export or export default to the functions. As a result there must be "success" rendered.

index.html
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<div class="root"></div>
<script src="invert.js"></script>
<script src="dom.js"></script>
<script src="render.js"></script>
<script src="reverse.js"></script>
<script>
window.render.renderDOM('.root', reverse('sseccus'));
</script>
</body>
</html>
render.js
const TAG = 'p';
function renderDOM(selector, content) {
const root = document.querySelector(selector);
if (!root) {
return;
}
const element = createElement(TAG, content);
root.appendChild(element);
}
window.render = {renderDOM};
dom.js
const createElement = (() => {
const TAG = 'div';
return function createElement(tag = TAG, content) {
const element = document.createElement(tag);
element.textContent = content;
return element;
}
})();

Related

HTML content is not added

I have a similar class structure and it doesn't work for me, I've already tried several things and can't fix the problem. As you can see, the constructors are executed correctly and also the method executed in the last constructor. However, when I create HTML content, it doesn't paint it. Why and how could you solve this?
class AutoComplete{
constructor(){
console.log("constructor autocomplete")
this.table = new Table();
}
}
class Table{
constructor(){
console.log("constructor table")
this.arr = []
fetch('https://jsonplaceholder.typicode.com/posts')
.then((response) => response.json())
.then((data) => {
data.map(d => this.arr.push(d))
});
this.fill();
}
fill = () => {
console.log("fill");
const content = document.querySelector("#content");
// doesn't work
this.arr.forEach( ct => {
const div = document.createElement("div");
div.innerText = ct.body;
content.appendChild(div);
//content.innerHTML += div;
});
}
}
let autoc = new AutoComplete();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
</head>
<body>
<div id="content"></div>
</body>
</html>
This is happening because you need to call this.fill() within the .then() callback function. Otherwise. this.fill is called before you get data back from the API.
Demo:
class AutoComplete{
constructor(){
console.log("constructor autocomplete")
this.table = new Table();
}
}
class Table{
constructor(){
console.log("constructor table")
this.arr = []
fetch('https://jsonplaceholder.typicode.com/posts')
.then((response) => response.json())
.then((data) => {
data.map(d => this.arr.push(d));
this.fill();
})
// this.fill()
}
fill = () => {
console.log("fill");
const content = document.querySelector("#content");
// doesn't work
this.arr.forEach(ct => {
const div = document.createElement("div");
div.innerText = ct.body;
content.appendChild(div);
//content.innerHTML += div;
});
}
}
let autoc = new AutoComplete();
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title></title>
</head>
<body>
<div id="content"></div>
</body>
</html>

Javascript callback called twice

I'm pretty new with coding, and this is really stumping me...
Here is my index.html file
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title></title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.0.0/animate.min.css">
<link rel="stylesheet" href="owlcarousel/owl.carousel.css">
<link rel="stylesheet" href="owlcarousel/owl.theme.default.css">
</head>
<body>
<div class="owl-carousel owl-theme">
</div>
<script src="https://code.jquery.com/jquery-3.5.1.js" integrity="sha256-QWo7LDvxbWT2tbbQ97B53yJnYU3WhH/C8ycbRAkjPDc=" crossorigin="anonymous" type="text/javascript" language="JavaScript"></script>
<script src="jquery.min.js"></script>
<script src="owlcarousel/owl.carousel.js"></script>
<script src="app.js"></script>
<script>
fetch('https://www.paulschlatter.com/slideshow/slideshows.txt')
.then((response) => response.text().then(yourCallback));
let cache = {}
function yourCallback(retrievedText, callback) {
if (cache[retrievedText]) {
console.log('oops')
} else {
let array = []
console.log(callback)
array = retrievedText.split(/\n|\r/g)
let httpsArray = []
let keysArray = []
let mappedArray = array.map(item => {
if (item.substring(0, 5) === 'https') {
httpsArray.push(item)
} else if (item.substring(0, 3) === '202') {
keysArray.push(item)
}
})
const object = { ...keysArray
}
for (const prop in object) {
window['value' + prop] = []
httpsArray.filter(item => item.includes(object[prop])).map(item => {
window['value' + prop].push(item)
})
}
const owlImages = document.querySelector('.owl-carousel'),
owlDiv = document.createElement('img');
owlDiv.setAttribute('src', window.value0.pop())
owlDiv.setAttribute('alt', '')
owlImages.appendChild(owlDiv)
}
}
</script>
</body>
</html>
I am not using npm or anything, just straight JavaScript, and HTML.
The function yourCallback is firing twice, so even when I only console.log hello world it returns hello world twice to my browser.
Obviously this is not ideal, and I believe that the problem lies in the
fetch('https://www.paulschlatter.com/slideshow/slideshows.txt')
.then((response) => response.text().ten(yourCallback));
This was a silly mistake, in my app.js file I had the same fetch and yourCallback function, so it was firing twice cause I called it twice :)

my code at first is correct but with this error spread.js.25 I can not see result in the browser

When I inspect the code in the browser this error appears spread.js.25 and I can not find this problem.
I checked the exercise solution, it's the same as my solution ... I don't know much about axios ...
<!DOCTYPE html>
<html lang="en">
<head>
<title>Exercício 02</title>
</head>
<body>
<input type="text" name="user">
<button onclick="listRepositories()">Adicionar</button>
<ul></ul>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script>
var listElement = document.querySelector('ul');
var inputElement = document.querySelector('input');
function renderRepositories(repositories) {
for (repo of repositories) {
const textElement = document.createTextNode(repo.name);
const liElement = document.createElement('li');
liElement.appendChild(textElement);
listElement.appendChild(liElement);
}
}
function listRepositories() {
var user = inputElement.value;
if (!user) return;
axios.get('https://api.github.com/users/' + user + '/repos')
.then(function (response) {
renderRepositories(response.data);
})
}
</script>
</body>
</html>
this image is exactly the problem

Why can I write to sessionStorage from an iframe on the first try, but not any consecutive tries? (Chrome Version 74)

This issue has shown up in the latest version of Chrome (74.0.3729.108). This is unique to the local filesystem, as I have other ways of loading up neighboring documents in iframes when the app is on a server.
In my app, we have been able to load up documents from the filesystem with JavaScript by writing iframes to the DOM, and then having the document in the iframe write it's innerHTML to sessionStorage. Once the iframe is done loading, we catch that with the onload attribute on the iframe and handle getting the item written to sessionStorage.
I have narrowed this down to some bare-bones code and found that this works only on the first try, and then any tries after the first fail.
Here is a minimal HTML document:
<!DOCTYPE html>
<html>
<head>
<title>Chrome iFrame Tester</title>
<script src="iframe-load.js"></script>
</head>
<body onload="OnLoad()">
<div id="result"></div>
</body>
</html>
Here is the JavaScript:
var urls = ['file://C:/Users/afrench/Documents/Other/Misc%20Code/Chrome%20iFrame/Doc1.html',
'file://C:/Users/afrench/Documents/Other/Misc%20Code/Chrome%20iFrame/Doc2.html'];
HandleLoad = function () {
'use strict';
var data;
try {
data = window.sessionStorage['data'];
delete window.sessionStorage['data'];
} catch (ignore) {
// something went wrong
}
var container = document.getElementById('container');
window.document.body.removeChild(container);
if (data !== null && data !== undefined) {
var resultContainer = document.getElementById('result');
resultContainer.innerHTML += data;
}
if (urls.length > 0) {
OnLoad();
}
}
function OnLoad() {
var url = urls[0];
if (url) {
urls.splice(0, 1);
var container = document.createElement('div');
container.id = 'container';
container.style.visibility = 'hidden';
window.document.body.appendChild(container);
container.innerHTML = '<iframe src="' + url + '" onload="HandleLoad();"></iframe>';
}
}
In the filesystem, we have the HTML written into index.html, and right next to it are two minimal HTML files, Doc1.html and Doc2.html. Their contents are both identical except the identifying sentence in the body's div:
Neighbor document HTML:
<!DOCTYPE html>
<html>
<head>
<title>Chrome iFrame Tester</title>
<script>
function OnLoad() {
try {
window.sessionStorage['data'] = window.document.body.innerHTML;
} catch {
// no luck
}
}
</script>
</head>
<body onload="OnLoad()">
<div>This is Doc 1's content!</div>
</body>
</html>
When this is run, we should see the content HTML of the two neighbor documents written to the result div in index.html.
When I run this minimal example, I can see that the content is successfully written to sessionStorage and then to the DOM for the first document, but the next try fails. What can I do to get it to work consistently, and what is happening here that it fails?
I'm not sure what is causing the weird behavior, so hopefully someone else can provide some insight on what exactly is going on here.
In the meantime, here is an alternative solution using window.postMessage:
index.html
<!DOCTYPE html>
<html>
<head>
<title>Chrome iFrame Tester</title>
<script src="iframe-load.js"></script>
</head>
<body onload="OnLoad()">
<div id="result"></div>
</body>
</html>
iframe-load.js
var urls = ['file://C:/Users/afrench/Documents/Other/Misc%20Code/Chrome%20iFrame/Doc1.html',
'file://C:/Users/afrench/Documents/Other/Misc%20Code/Chrome%20iFrame/Doc2.html'];
window.addEventListener('message', event => {
'use strict';
var data = event.data;
var container = document.getElementById('container');
window.document.body.removeChild(container);
if (data) {
var resultContainer = document.getElementById('result');
resultContainer.innerHTML += data;
}
if (urls.length > 0) {
OnLoad();
}
})
function OnLoad() {
var url = urls.shift();
if (url) {
var container = document.createElement('div');
container.id = 'container';
container.style.visibility = 'hidden';
window.document.body.appendChild(container);
container.innerHTML = '<iframe src="' + url + '"></iframe>';
}
}
Doc1.html
<!DOCTYPE html>
<html>
<head>
<title>Chrome iFrame Tester</title>
<script>
function OnLoad() {
window.parent.postMessage(window.document.body.innerHTML, '*');
}
</script>
</head>
<body onload="OnLoad()">
<div>This is Doc 1's content!</div>
</body>
</html>

Extract a variable value in JavaScript code from HTML

I'm getting the HTML code of a webpage using this parsing library called Kanna. Basically the stripped down version looks like this.
<!DOCTYPE html>
<html lang="en" class="no-js not-logged-in client-root">
<head>
<meta charset="utf-8">
</head>
<body>
<script type="text/javascript">
window._sharedData = {
// Some JSON
};
</script>
<script type="text/javascript">
// Javascript code
</script>
<script type="text/javascript">
// More Javascript code
</script>
</body>
</html>
There are multiple script tags within the body. I want to access the one with the variable named window._sharedData and extract it's value which is a JSON dictionary.
I tried with using regular expressions but it's returning nil. Maybe something's wrong with my pattern?
if let doc = try? HTML(url: mixURL, encoding: .utf8), let body = doc.body, let htmlText = body.text {
let range = NSRange(location: 0, length: htmlText.utf8.count)
let regex = try! NSRegularExpression(pattern: "/<script type=\"text/javascript\">window._sharedData = (.*)</script>/")
let s = regex.firstMatch(in: htmlText, options: [], range: range)
print(s)
}
Or is there a better way to do this?
Here it is:
import Foundation
import Kanna
let htmlString = "<!DOCTYPE html><html lang=\"en\" class=\"no-js not-logged-in client-root\"><head> <meta charset=\"utf-8\"></head><body> <script type=\"text/javascript\"> window._sharedData = { \"string\": \"Hello World\" }; </script> <script type=\"text/javascript\"> </script> <script type=\"text/javascript\"> </script></body></html>"
guard let doc = try? HTML(html: htmlString, encoding: .utf8) else { print("Build DOM error"); exit(0) }
let body = doc.xpath("//script")
.compactMap { $0.text }
.filter { $0.contains("window._sharedData") }
.map { $0.replacingOccurrences(of: " window._sharedData = ", with: "") }
.map { $0.dropLast(2) }
.first
print("body: ", body)
// body: Optional("{ \"string\": \"Hello World\" }")
After that you can check that body not nil and ready

Categories

Resources