Polymer core-label and core-checkbox dynamic - javascript

I'm trying to generate a list of core-label elements with javascript.
In the documentation(https://www.polymer-project.org/docs/elements/core-elements.html#core-label) it is written, that I may add the attribute for in an input-element inside the core-label to connect them.
If I code it static like this, it is possible:
<core-label>
<core-image></core-image>
<paper-checkbox for></paper-checkbox>
<span>Text</span>
</core-label>
But if i try to add those elements dynamic inside a script, those elements are not connected...
var catLayout = document.createElement("core-label");
var img = document.createElement("core-image");
var chk = document.createElement("paper-checkbox");
chk.setAttribute("for","");
var label = document.createElement("span");
var labelcontent = document.createTextNode("text");
label.appendChild(labelcontent);
catLayout.appendChild(img);
catLayout.appendChild(chk);
catLayout.appendChild(label);
May anyone tell me, whats wrong?

What you're doing should work. I wonder if you're running into a timing issue due to the way you're script is being executed within the larger context of your application. But here's a functionally equivalent snippet that does the job:
<!doctype html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<script src="//www.polymer-project.org/webcomponents.js"></script>
<link rel="import" href="//www.polymer-project.org/components/core-label/core-label.html">
<link rel="import" href="//www.polymer-project.org/components/paper-checkbox/paper-checkbox.html">
<div>
<core-label>
<paper-checkbox for></paper-checkbox>
<span>Created via Markup</span>
</core-label>
</div>
<div id="container"></div>
<script>
var coreLabel = document.createElement('core-label');
var paperCheckbox = document.createElement('paper-checkbox');
paperCheckbox.setAttribute('for', '');
var text = document.createElement('span');
text.textContent = 'Created via JavaScript';
coreLabel.appendChild(paperCheckbox);
coreLabel.appendChild(text);
document.querySelector('#container').appendChild(coreLabel);
</script>
</body>
</html>
That being said, I'm curious as to why you need to create these elements via JavaScript. I personally find Polymer code much easier to read and maintain when as much as possible is handled via the DOM using Polymer's <template> logic. For instance, if you're resorting to JavaScript element creation because you want to include these elements conditionally, wrapping <template if="{{your_condition}}"> around that section of your DOM could take care of that for you. Similarly, if you're doing this from JavaScript because you want to repeat the logic multiple times for each element in an array, <template repeat="{{item in your_array}}"> can handle that for you. The data-binding section of the docs is great if you haven't seen it.

Related

Is it possible to use javascript to modify a script element?

Is there a way to use javascript to modify a script element?
Like for example:
HTML:
<script id="something" src="/js/file.js"></script>
Javascript:
var something = document.getElementById("something");
something.src = "/js/anotherfile.js"
Is it possible? Because I have a bit of code that works like that and it sort of doesn't work
To be specific, here's the code:
<!DOCTYPE html>
<html>
<head>
<title>MyohTheGod's Website</title>
<link rel="icon" type="image/x-icon" href="/supercorn.gif" defer>
</link>
<link id="css" href="/css/dark.css" rel="stylesheet" type="text/css">
</link>
<script src="/js/particles.js" defer></script>
<script src="/js/header.js"></script>
<script src="/js/theme.js"></script>
<script>window.alert("Welcome to the Home of MyohTheGod. You can play games, check out our web proxies, and more. Also, please do check out the About page. Press OK to continue...");</script>
</head>
<body>
-snip-
</body>
<script id="foot" src="/js/footer.js"></script>
</html>
<script>
-snip-
</script>
var css = document.getElementById("css");
var foot = document.getElementById("foot");
function toggleDLmode(m) {
-snip-
if (dlmodebool) {
css.href = "/css/dark.css"
foot.src="/js/dark-footer.js"
} else {
css.href = "/css/index.css"
foot.src="/js/footer.js"
}
}
-snip-
It is working, do you inspect it? It does changed, but maybe you're thinking, "hm why this /js/anotherfile.js is not downloaded?". Well because of the script tag is already rendered and already downloaded, so you can't do that. What you can do though add NEW script tag.
Maybe this will help How to dynamically change the script src?. This links would explain more why your code "does not work".
There certainly is. You can use document.scripts which returns an collection that you can iterate through like an array. You can change the code using the innerHTML property very much like a normal element. See here https://developer.mozilla.org/en-US/docs/Web/API/HTMLCollection
Edited to add: If you've got a html page with multiple script tags, the document.script collection has each script in the order they appear. The code below will log out the source (src tag) or the actual javascript for each script element.
You can also 'write' javascript by setting the innerHTML property.
IMHO it's a bit of a solution that's looking for a problem but at least it gives you access to the number of scripts you have.
[...document.scripts].forEach(script => {
if (script.src != '') {
console.log("Script source:" + script.src);
} else {
console.log(script.innerHTML);
}
});

How do I make the querySelector look in a specific included document only?

On my index page I have a number of includes.
<section><?php include('content/content1.php') ?></section>
<section><?php include('content/content2.php') ?></section>
<section><?php include('content/content3.php') ?></section>
In each of them I have a unique script (and some other things which is not shown here).
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Content1</title>
<link rel="stylesheet" href="content/sketch.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.5.10/p5.js"></script>
</head>
<body>
<div class="frame">
<canvas></canvas>
</div>
<script src="content/content1.js"></script>
</body>
The <canvas> tag is what the querySelector in the javascript calls to.
var canvas = document.querySelector('canvas');
This works, but only for the first content file. It seems the querySelector looks at the whole loaded page, instead of just inside the body of the document where the script is placed. Google console says: "Indentifier 'canvas' has already been declared".
I have tried setting an id on the canvas-element:
<canvas id="canvas1"></canvas>
var canvas = document.querySelector('#canvas1');
But it's not working. How do I get around this?
You can use document.currentScript to get the tag of the currently running script tag. From there, you can navigate to its containing section, and from there, get to the canvas descendant.
You should also put everything into an IIFE to avoid global variable collisions.
(() => {
const canvas = document.currentScript.closest('section').querySelector('canvas');
// ...
})();

Import entire HTML page into another page

I'm trying to embed another website within my website but I don't want to do it with an iFrame or AJAX import due to some issues that would cause.
<html>
<head>
<link rel="import" href="mysite.html">
</head>
<body>
<script>
var link = document.querySelector('link[rel="import"]');
var content = link.import;
document.body.appendChild(content.cloneNode(true));
</script>
</body>
</html>
Basically I'm trying to do this with HTML Imports from Web Components but unfortunately what I have above does not work (I am using the right browser too) and all the examples I've found were only for importing a specific div or element from within an imported page. But is it possible to simply load the entire page and embed it in another site?
It doesn't work because the object you get from the import property of the <link rel="import"> element is a Document interface.
You cannot insert this type of object inside a <body> element.
Instead you should at least get the <html> element of the imported document from its documentElement property:
var content = link.import.documentElement //returns a html element
But it still incorrect because you will then insert a <html> element inside a <body> element, which is ugly.
You'd rather copy the innerHTML text of the imported document to the main one:
document.body.innerHTML = link.import.querySelector( 'body' ).innerHTML
Or put the HTML you want to import inside a <template>, which is better if you want to defer scripts execution and loadings.

Render math with KaTeX in the browser

I am using KaTeX to render math in the browser.
Right now I am using something like
document.getElementById('el').innerHTML = function () {
const span = document.createElement('span');
katex.render('2+\frac{1}{x}', span);
return span.innerHTML;
});
but it seems really stupid that I have to apply it to an element, and then take the html from this element and insert in my string.
I have looked through the KaTeX documentation, but I cannot find anything to help me just rendering some text directly in the browser with something like katex.render('2+3+4').
I don't know if you're still looking for an answer but maybe this will be helpful.
First, I link to katex.min.js and katex.min.css from a cdn.
I wrap everything I want rendered in katex inside span tags and give them the class 'math'
For example:
<span class='math'>2+\frac{1}{x}</span>
Then inside a pair of script tags I include something like this:
var math = document.getElementsByClassName('math');
for (var i = 0; i < math.length; i++) {
katex.render(math[i].textContent, math[i]);
}
So as long as I write my math text inside an element with the class math, it gets rendered by katex.
EDIT: We should use textContent instead of innerHTML. I've run into issues using innerHTML. See using katex, '&' alignment symbol displays as 'amp;'
Use KaTeX's auto-render extension, which will let you add your KaTeX directly to the HTML with a delimiter like $$ and then render it all at once:
<!doctype html>
<html>
<head>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/katex.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.7.1/contrib/auto-render.min.js"></script>
</head>
<body>
<div id="el"><span>$$2+\frac{1}{x}$$</span></div>
<script>
renderMathInElement(document.body);
</script>
</body>
</html>

How to replace Current script tag with HTML contents generated by the same script

I want to replace the current script tag with the HTML contents generated by the same script.
That is, my Page is
<html>
<body>
<div>
<script src="myfile1.js"></script>
</div>
<div>
<script src="myfile1.js"></script>
</div>
</body>
</html>
Inside each .js file corresponding html contents are generated. I want to put the contents as the innerHTML of the parent div. But can't set id for the parent div because the page is not static. So the current script tag must be replaced with the HTML content. How can I do this?
For each script tag src is the same. So can't identify with src. These scripts displays
some images with text randomly. Scripts are the same but displays different contents in divs on loading
Please help me
try inside of myfile1.js:
var scripts = document.getElementsByTagName( "script" );
for ( var i = 0; i < scripts.length; ++ i )
{
if ( scripts[i].src == "myfile1.js" )
{
scripts[i].parentNode.innerHTML = "new content";
}
}
This is a great question for those trying to implement a JSONP widget. The objective is to give the user the shortest possible amount of code.
The user prefers:
<script type="text/javscript" src="widget.js"></script>
Over:
<script type="text/javscript" src="widget.js"></script>
<div id="widget"></div>
Here's an example of how to achieve the first snippet:
TOP OF DOCUMENT<br />
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
// inside of widget.js
document.write('<div id="widget"></div>');
$(document).ready(function() {
$.getJSON('http://test.com?remote_call=1', function(data) {
$('#widget').html(data);
});
});
<br />BOTTOM OF DOCUMENT
Have a look at: http://alexmarandon.com/articles/web_widget_jquery/ for the correct way to include a library inside of a script.
document.currentScript has been available since 2011 on Firefox and 2013 on Chrome.
document.currentScript documentation at MDN
<!DOCTYPE html>
<meta charset="UTF-8">
<title>currentScript test</title>
<h1>Test Begin</h1>
<script>
document.currentScript.outerHTML = "blah blah";
</script>
<h1>Test End</h1>
Unfortunately a running JavaScript file is not aware of where it is running. If you use document.write() in the script, the write function will take place wherever the script runs, which would be one way to accomplish what you want, but without replacing the contents or being able to perform any actions on the enclosing DIV.
I can't really envisage a situation where you'd have such stringent restrictions on building a page - surely if the page is dynamic you could generate identifiers for your DIV elements, or load content in a more traditional manner?
Why not use Smarty?
http://www.smarty.net/
You can use javascript in Smarty templates, or just use built-in functions.
Just take a look at http://www.smarty.net/crash_course
poof -- old answer gone.
Based on your last edit, here's what you want to do:
<html>
<head>
<!-- I recommend getting this from Google Ajax Libraries
You don't need this, but it makes my answer way shorter -->
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function(){
function getRandomContent(){
// I expect this is the contents of your current script file.
// just package it into a function.
var rnd = Math.random();
return "[SomeHtml]";
}
$('.random').each(idx, el){
$(this).html(getRandomHtmlContent());
});
});
</script>
</head>
<body>
<div class="random">
</div>
<div class="random">
</div>
</body>
</html>
If you don't mind the script tag remaining in place you can use something as simple as document.write().
myfile1.js:
document.write("<p>some html generated inline by script</p>");
It will do exactly what you need.

Categories