Web Component Template Error - javascript

Here is my index.html file:
<!DOCTYPE html>
<html>
<head>
<script src="webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="test-component.html">
</head>
<body>
<test-component id ="host">
<p>test</p>
</test-component>
</body>
</html>
And here is the test-component.html file:
<template id = "template">
<p> this is the shadow dom</p>
<content select = "p"></content>
</template>
<script>
var test_component = document.registerElement("test-component", {
prototype: Object.create(HTMLElement.prototype,{
createdCallback:{
value: function(){
var host = document.querySelector("#host");
var root = host.createShadowRoot();
var template = document.querySelector("#template");
var content = document.importNode(template.content, true);
root.appendChild(content);
}
}
})
});
</script>
for some reason I'm getting an error on this line:
var content = document.importNode(template.content, true);
The error is:
Uncaught TypeError: Cannot read property 'content' of null
Anyone know why this is happening?

in test-component.html try this way to get template
var template = document.currentScript.ownerDocument.querySelector("#template");

I had the same issue. I have a placeholder that acts as a navigation system for web components. The first component displayed (hard written in the html page) was loaded correctly thanks to Sigma's tip, but I couldn't get the second component (created through an event from the first component) to load correctly.
Here is how I did:
<template id="my-component-template">
Hello World!
</template>
<script>
(function() {
// Keep track of the document that contains the template
let doc = document.currentScript.ownerDocument;
window.customElements.define('my-component', class extends HTMLElement {
constructor() {
super();
let shadowRoot = this.attachShadow({mode: 'open'});
const t = doc.querySelector('#my-component-template');
const instance = t.content.cloneNode(true);
shadowRoot.appendChild(instance);
}
});
})();
</script>

As I know you can't use template so.
First of all you can move your template into index.html then your sample will work fine:
<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<script src="webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="test-component.html">
</head>
<body>
<template id = "template">
<p> this is the shadow dom</p>
<content select = "p"></content>
</template>
<test-component id ="host">
<p>test</p>
</test-component>
</body>
</html>
Live sample from http://webcomponents.org: jsbin
Another option - create your shadow dom without using templates:
<!--index.html-->
<!DOCTYPE html>
<html>
<head>
<script src="webcomponentsjs/webcomponents.js"></script>
<link rel="import" href="test-component.html">
</head>
<body>
<test-component id ="host">
<p>test</p>
</test-component>
</body>
</html>
<!--test-component.html-->
<script>
var test_component = document.registerElement("test-component", {
prototype: Object.create(HTMLElement.prototype,{
createdCallback:{
value: function() {
var host = document.querySelector("#host");
var root = host.createShadowRoot();
var paragraph = document.createElement("p");
paragraph.innerHTML = "this is shadow dom";
var content = document.importNode(paragraph, true);
root.appendChild(content);
}
}
});
});
</script>

Related

Access to javascript module Class/object from index.html

I defined Class in my javascript file...I imported that file into html page:
<script type="module" src="./js/controller.js"></script>
How can I now acces to classes inside of that js file?
I want to have something like this (in my html file):
<script>
let app = null;
document.addEventListener('DOMContentLoaded', function () {
//Init app on DOM load
app = new MyApp();
});
</script>
But it doesn't work (I get Uncaught ReferenceError: MyApp is not defined)...If I include this DOMContentLoaded listener into end of my controller.js file, It works. But I lost reference to app variable this way (which I don't want)... Is there way to have reference to something defined in modules?
Most important reason why I want to have that reference is ability to access to my app object from google chrome console...
Thanks!
You can access your class in js file from html in the following way-
My Home.html file:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8'>
<meta http-equiv='X-UA-Compatible' content='IE=edge'>
<title>Page Title</title>
<meta name='viewport' content='width=device-width, initial-scale=1'>
<script type="module">
import { Car } from "./main.js";
let obj= null;
alert("Working! ");
obj = new Car("Mini", 2001);
obj.PrintDetails();
document.addEventListener('DOMContentLoaded', function () {
let obj2 = new Car("Merc", 2010);
obj2.PrintDetails();
});
</script>
</head>
<body>
<h1> Lets try something <br></h1>
</body>
</html>
My main.js file:
export class Car {
constructor(name, year) {
this.name = name;
this.year = year;
}
PrintDetails() {
console.log(" Name = "+ this.name);
console.log(" year = "+ this.year);
}
}

Why can I call function which is in a shadow dom?

I created a custom element called "memory-box" like the below code.
Please pay attention to the function "logthis" which is in "memory-box-template".
memory-box.html
<template id="memory-box-template">
<input id="memory-box" type="form" />
<input type="button" id="testbutton" />
<script type="text/javascript">
function logthis(me){
console.log(me);
}
</script>
</template>
<script type="text/javascript">
(function() {
var thisDoc = document.currentScript.ownerDocument;
var storage = localStorage;
var proto = Object.create(HTMLElement.prototype, {
createdCallback: {
value: function() {
var temp = thisDoc.querySelector('#memory-box-template');
var con = document.importNode(temp.content, true);
this.createShadowRoot().appendChild(con);
var input = this.querySelector('::shadow #memory-box');
var data = storage.getItem(this.id);
input.value = data;
input.addEventListener('input', saveData.bind(input, this.id));
}
},
});
document.registerElement('memory-box', {
prototype: proto
});
function saveData(id, e) {
storage.setItem(id, this.value);
}
})();
</script>
Now, I uses the custom element "memory-box" like the below code.
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<link rel="import" href="/html/memory-box.html">
</head>
<body>
<div><memory-box id="memory1"></memory-box></div>
<div><memory-box id="memory2"></memory-box></div>
<div><memory-box id="memory3"></memory-box></div>
<div><memory-box id="memory4"></memory-box></div>
</body>
<script type="text/javascript">
logthis(this);
</script>
</html>
As you can see, I putted a script in the index.html and called the function "logthis" just because I was curious. And no error occurred.
Why?
The function "logthis" is in each shadow doms. It's supposed not able to be called outside the shadow dom, I think.
As explained here, while the HTML within Shadow DOM is encapsulated, any JavaScript is NOT -- it is in the global scope, unless you utilize specific javascript techniques (namescaping, IIFE) to do so.
Hope this helps,
Jonathan Dodd

actually creating a webpage with javascript

An extremely simple question but I am noob. I have been learning javascript and jquery for a while on jsfiddle, there everything works fine, building cool quizzes and all, but when I tried to actually create a directory, reference the jquery library and my javascript file, nothing works, even the below code, when saved as an HTML file doesn't work. I just paste it into notepad and save it as html, when I open it with it doesn'T work.
<html>
<head>
<title>webpage</title>
<script type="text/javascript">
window.onload = function() {
var myDiv = document.getElementById('#div');
myDiv.appendChild(document.createTextNode("Hi my name is Mehmetcan"));
}
</script>
</head>
<body>
<div id="myDiv"> </div>
</body>
</html>
Use this as starting point:
<html>
<head>
<script src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<title>webpage</title>
<script type="text/javascript">
$(document).ready(function () {
var myDiv = document.getElementById('myDiv');
myDiv.appendChild(document.createTextNode("Hi my name is Mehmetcan"));
});
</script>
</head>
<body>
<div id="myDiv"> </div>
</body>
Another approach that doesn't rely on JQuery but on pure, vanilla javascript.
<html>
<head>
<title>webpage</title>
<script type="text/javascript">
document.body.onload = loadSite;
function loadSite() {
var newDiv = document.createElement("span");
var newContent = document.createTextNode("Hi there and greetings!");
newDiv.appendChild(newContent);
myDiv.appendChild(newDiv);
}
</script>
</head>
<body>
<div id="myDiv"> </div>
</body>
</html>
You can find the full javascript sample as well as more information here, on the document.createElement MDN pages.
document.body.onload = addElement;
var my_div = null;
var newDiv = null;
function addElement () {
// create a new div element
// and give it some content
var newDiv = document.createElement("div");
var newContent = document.createTextNode("Hi there and greetings!");
newDiv.appendChild(newContent); //add the text node to the newly created div.
// add the newly created element and its content into the DOM
my_div = document.getElementById("org_div1");
document.body.insertBefore(newDiv, my_div);
}

Javascript/JSON error: not well formed

I am testing putting a text editor on my page and storing it as part of a JSON object.
HTML
<!DOCTYPE html>
<html>
<head>
<script src="http://tinymce.cachefly.net/4.0/tinymce.min.js" type="text/javascript"> </script>
<script type="text/javascript">
tinymce.init({
selector: "textarea"
});
</script>
<link rel="stylesheet" href="/jquery.mobile-1.3.2.min.css"/>
<script src="/jquery-1.9.1.min.js"></script>
<script src="/jquery.mobile-1.3.2.min.js"></script>
</head>
<body>
<form method="post" action="formSubmit.js">
<textarea name ="editor"></textarea>
<p><input type="submit" value="Submit"></p>
</form>
</body>
</html>
JS
$(document).ready(function () {
var text = $("editor").val();
var name = "project name";
var id = 5;
var item = new item(name, text, id);
var itemArray = localStorage.items;
if (itemArray == undefined) {
itemArray = [];
} else {
itemArray = JSON.parse(itemArray);
}
itemArray.push(item);
localStorage.items = JSON.stringify(itemArray);
});
I want to be able to store item in a JSON object. When I run this I receive a "not-well formed" error at line 1 of the Javascript. It's a very simple program I'm running and can't seem to pinpoint what is causing the error. Is the JSON done incorrectly or are scripts in my HTML header causing issues?
$("editor") is looking for an html tag called 'editor'. you probably want to attach an id attribute to your and do $('#editor')

How to pass div ids to javascript at onload?

I have an Html file like this:
<!doctype html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="style/boxClass.css" />
<script type="text/javascript">
/* lightBox class */
function box (id1,id2) {
this.boxBackgroundDiv = document.getElementById (id1);
this.boxWorkAreaDiv = document.getElementById (id2);
}
lightBox.prototype.setBackgroundColor = function(c) {
this.boxBackgroundDiv.style.backgroundColor = c;
alert('Hello back');
};
function init (id1,id2)
{
boxObj = new box (id1,id2);
alert ("Hello");
}
</script>
</head>
<body onload="init('box1','box2')">
<div id="lightbox1" class="boxBackground">I am here</div>
<div id="lightbox2" class="boxWorkArea"><button onclick="boxObj.setBackgroundColor('Red')">I am here</button></div>
</body>
</html>
Now when I call my init function the way it is in this code via it works fine. But if I do as below via window.onload, it does not work. its not able to get the div ids in this case. But I need div ids to crate objs for my class.
<!doctype html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="style/boxClass.css" />
<script type="text/javascript">
/* lightBox class */
function box (id1,id2) {
this.boxBackgroundDiv = document.getElementById (id1);
this.boxWorkAreaDiv = document.getElementById (id2);
}
lightBox.prototype.setBackgroundColor = function(c) {
this.boxBackgroundDiv.style.backgroundColor = c;
alert('Hello back');
};
function init (id1,id2)
{
boxObj = new box (id1,id2);
alert ("Hello");
}
window.onload = init ("box1",box2);
</script>
</head>
<body>
<div id="lightbox1" class="boxBackground">I am here</div>
<div id="lightbox2" class="boxWorkArea"><button onclick="boxObj.setBackgroundColor('Red')">I am here</button></div>
</body>
</html>
Two issues:
1) You are missing quotes around box2 parameter,
2) You are assigning the return value of init function (which here is a void) to window.onload handler.
You should assign the onload handler as below:
window.onload = function(){
init ("box1","box2");
}

Categories