I am following this tutorial on the shadow DOM:
http://www.html5rocks.com/en/tutorials/webcomponents/shadowdom/
For some reason, when I call the createShadowRoot function on the element, that element becomes invisible.
Here is my code:
<div id="nameTag">Bob</div>
<template id="nameTagTemplate">
<style>
.outer {
border: 2px solid brown;
}
</style>
<div class="outer">
<div class="boilerplate">
Hi! My name is
</div>
<div class="name">
Bob
</div>
</div>
</template>
<script>
var shadow = document.querySelector('#nameTag').createShadowRoot();
// var template = document.querySelector('#nameTagTemplate');
// shadow.appendChild(template.content.cloneNode());
</script>
When I don't call this method then the code works fine.
Any ideas why it is making it invisible?
Thanks :)
The main objective of shadow DOM is separation of content from presentation. Read: The content is in the document; the presentation is in the Shadow DOM
In Shadow DOM <content> acts as the insertion point for the content (in this case,
the text 'Bob' in the element) we want to show . Without this, the content, though already available in the document, can't be presented.
So, You need to modify your code to this -
<template id="nameTagTemplate">
<style></style>
<div class="outer">
<div class="boilerplate">
Hi! My name is
</div>
<div class="name">
<content></content>
</div>
</div>
</template>
And, try using
var shadow = document.querySelector('#nameTag').createShadowRoot();
var template = document.querySelector('#nameTagTemplate');
//shadow.appendChild( template.content.cloneNode() ); // does not work
shadow.appendChild( template.content.cloneNode(true) );
// or
shadow.appendChild( template.content );
using pure javascript:
// shadow DOM example with <template> and template string
//
var nameTag = function(selector, newName)
{
var name = newName || document.querySelector(selector).innerHTML;
var shadow = document.querySelector(selector).createShadowRoot();
var templateNode = createNameTagTemplate(name);
var clone = document.importNode(templateNode, true);
shadow.appendChild(clone.content);
};
function createNameTagTemplate(name)
{
var templateNode = document.createElement("template");
templateNode.innerHTML = `
<style>
.outer {
border: 2px solid brown;
border-radius: 1em;
background: red;
font-size: 20pt;
width: 12em;
height: 7em;
text-align: center;
}
.boilerplate {
color: white;
font-family: sans-serif;
padding: 0.5em;
}
.name {
color: black;
background: white;
font-family: "Marker Felt", cursive;
font-size: 45pt;
padding-top: 0.2em;
}
</style>
<div class="outer">
<div class="boilerplate">
Hi! My name is
</div>
<div class="name">
${name}
</div>
</div>`;
return templateNode;
}
then if you have this:
<div id="foo">Bob</div>
nameTag("#foo") will make the div into a nametag using current name, or
nameTag("#foo", "Joe") will make it for name "Joe" instead.
NOTE: Supported in Firefox behind the dom.webcomponents.enabled flag (about:config).
Related
I am trying to create a simple post adder in Javascript. For some reason, it won't push my input. What am I doing wrong? Is there a better alternative to doing this?
let posts = [];
function sendPost () {
let post = document.getElementById("post").value;
document.getElementById("postSender").innerHTML=(post);
}
input {
background: lightgrey;
border: none;
padding: 10px;
border-radius: 15px;
outline-width: 0;
}
::placeholder {
color: grey;
}
<div id="app">
<div>
<input type="text" placeholder="hi" id="post">
<button value="submit" #click="sendPost();"> Hi
</div>
<div id="postSender">
<p>
</p>
</div>
</div>
Change your #click to onClick and change innerHTML value equal to your let post
const posts = [];
function sendPost () {
let HTML = '';
let post = document.getElementById("post").value;
posts.push(post);
posts.forEach(function(item) {
HTML += '<div>' + item + '</div>';
});
document.getElementById("postSender").innerHTML = HTML;
}
input {
background: lightgrey;
border: none;
padding: 10px;
border-radius: 15px;
outline-width: 0;
}
::placeholder {
color: grey;
}
<div id="app">
<div>
<input type="text" placeholder="hi" id="post">
<button value="submit" onClick="sendPost()"> Hi</button>
</div>
<div id="postSender"></div>
</div>
Edit: post added to posts array and displayed in separate divs
Update the #click to onclick and y create functions to grab the HTML elements.
Here is one way to do it:
//function that grab te input value
function getInputValue(){
return document.getElementById("post").value
}
//function that grab the div with id "postSender"
function getDivPostSender(){
return document.getElementById("postSender")
}
function sendPost () {
//create a ne p tag element
let pEl = document.createElement('p')
//Appends the p Tag to the div with id "postSender"
getDivPostSender().appendChild(pEl)
//Update the text on the p tag element.
pEl.innerText = getInputValue()
}
input {
background: lightgrey;
border: none;
padding: 10px;
border-radius: 15px;
outline-width: 0;
}
::placeholder {
color: grey;
}
<div id="app">
<div>
<input type="text" placeholder="hi" id="post">
<button onclick="sendPost()">Submit</button>
</div>
<div id="postSender">
</div>
</div>
this line is wrong
let post = document.getElementById("post").value
it should be
let post = document.getElementById("postSender").value
Mouse on one element and another do the action, and only the other one has action.
I want to make a mouse on and change background colour effect, but it works on only one.
Whatever the mouse is pointing on, only one will change the colour.
Here is the code (HTML with JS)
<div class = science style = "position:absolute; left:20px">
<script language="javascript">
function hightback() {
document.getElementById("part1").style.backgroundColor = "#744e4e";
}
function removehightback() {
document.getElementById("part1").style.backgroundColor = "#524c44";
}
</script>
<button id = "part1" onclick="window.location.href='science.html';" value="science" onmouseover="hightback()" onmouseout="removehightback()">
<div class = science1 style = "position:absolute; left:40px; top:45px;">
<h1>Science</h1>
</div>
</button>
</div>
<div class=art style="position:absolute; left:280px">
<script language="javascript">
function hightback() {
document.getElementById("part2").style.backgroundColor = "#744e4e";
}
function removehightback() {
document.getElementById("part2").style.backgroundColor = "#524c44";
}
</script>
<button id="part2" onclick="window.location.href='art.html';" value="art" onmouseover="hightback()" onmouseout="removehightback()">
<div class=art1 style="position:absolute; left:40px; top:45px;">
<h1>Art</h1>
</div>
</button>
</div>
Here is the CSS:
.science1 h1 {
color: #b6ab8f;
size: 55;
font-family: "Josefin Sans", sans-serif;
text-align: left;
}
.science button {
border-radius: 50px;
background: #524c44;
padding: 20px;
width: 230px;
height: 300px;
}
.art1 h1 {
color: #b6ab8f;
size: 55;
font-family: "Josefin Sans", sans-serif;
text-align: left;
}
.art button {
border-radius: 50px;
background: #524c44;
padding: 20px;
width: 230px;
height: 300px;
}
You overwrite your functions for part2. Why not make one unique function for all elements?
Please check below example:
function changeBgColor(id, color) {
document.getElementById(id).style.backgroundColor = color;
}
And now you can use them in such way
<button id="part1"
onclick="window.location.href='art.html';"
value="art"
onmouseover="changeBgColor('part1', '#744e4e')"
onmouseout="changeBgColor('part1', '#524c44')" >
<div class=art1 style="position:absolute; left:40px; top:45px;">
<h1>Art</h1>
</div>
</button>
<button id="part2"
onclick="window.location.href='art.html';"
value="art"
onmouseover="changeBgColor('part2', '#744e4e')"
onmouseout="changeBgColor('part2', '#524c44')" >
<div class=art1 style="position:absolute; left:40px; top:45px;">
<h1>Art</h1>
</div>
</button>
Also you can simplify your code and instead of js use css styles
#part1, #part2 {
backgound-color: #524c44;
}
#part1:hover, #part2:hover {
backgound-color: #744e4e;
}
Your problem here is overlapping JS code as it is calling the second version of the function in the next script tag. I suggest using css hover instead.
Example:
#part_1:hover {
background-color: black;
}
In my javascript Program I have created a page to display an image and description at the same time when the user moves the mouseOver a link, and display a different image with no description when user moves the mouseOut of link. but I am not getting output on mouseOver/mouseOut as per expectation. Can anyone help ? I did the following:
(i) When the mouse moves over a link, I am calling the function by passing the text and image.
(ii) When the mouse moves out,I am calling the function by passing a blank text and a different image. This image is the same when the mouse is out from all the links.
code:
<!DOCTYPE html>
<html>
<head>
<style>
div a{
text-decoration: none;
font-size: 25px;
color: yellow;
}
.container {
width: 1002px;
margin-top: 50px;
margin-left: 130px;
}
#first {
width: 400px;
float: left;
height: 350px;
background-color:#f4b2ef;
border:inset;
}
#second {
width: 590px;
float: right;
height: 350px;
color: white;
border:inset;
}
</style>
<title>mouseover/out</title>
</head>
<body background="images/back.jpg">
<h1 style="text-align: center; font-family: monospace; color: white; font-size: 35px">PHOTO CONTEST </h1>
<div class='container'>
<div id="first">
<p style="text-align:center">First Place Winner</p>
<p style="text-align:center">Third Place Winner</p>
<p style="text-align:center">Merit Prize Winner</p>
<p id="para"> </p>
</div>
<div id="second">
<img id="default" src="images/default.jpeg" alt=""
width="590" height="350"/>
</div>
</div>
<script>
var blank = "";
var txt = "Beautiful fall";
var txt2 = "Natural pictures are beautiful";
var txt3 = "Beautiful Rose garden"
var w1 = new Image(590, 350);
var w2 = new Image(590, 350);
var w3 = new Image(590, 350);
var def = new Image(590, 350);
w1.src = "images/w1.jpeg";
w2.src = "images/w2.jpg";
w3.src = "images/w3.jpg";
def.src = "images/default.jpeg";
function replaceImg(txt, w1) {
w1.src;
var para = document.getElementById("para").innerHTML = txt;
}
function defaultImg(blank, def) {
def.src;
var para = document.getElementById("para").innerHTML = blank;
}
</script>
</body>
</html>
I amputate your code just to demonstrate that you can make it work by using js function addEventListener("moustover",callback) to do the work. I have never wrote code in your way so I don't know how to improve upon yours. You should always seperate your html css and js codes.
var firstTarget = document.querySelector("#first");
firstTarget.addEventListener("mouseover",function(){
document.querySelector("#target-image").setAttribute("src",'https://via.placeholder.com/350x150)');
})
firstTarget.addEventListener("mouseout",function(){
document.querySelector("#target-image").setAttribute("src",'#');
})
<!DOCTYPE html>
<html>
<head>
<title>mouseover/out</title>
</head>
<body background="images/back.jpg">
<h1 style="text-align: center; font-family: monospace; color: white; font-size: 35px">PHOTO CONTEST </h1>
<div class='container'>
<div id="first">
First Place Winner</p>
</div>
<div>
<img id="target-image" src="#" alt="">
</div>
</div>
I have a main-div and two divs with the class of container. The div with the class of container has a child div with a class of content with different contents. I'd like for the user to click on their choice of containers and transport its content to main-div. Then when the user clicks on the main-div, I'd like to transport that content back to its original div.
I'm not sure how to detach the content from main-div once it's been passed and reinsert it back into its original parent. I would appreciate any help.
I can't use IDs. I can only uses classes.
HTML
<div class="main-div">
</div>
<div class="container">
<div class="contents">
A
</div>
</div>
<div class="container">
<div class="contents">
B
</div>
</div>
CSS
.main-div {
width: 100wv;
height: 200px;
background: yellow;
cursor: pointer;
}
.container {
width: 40vw;
height: 150px;
border: 2px solid purple;
display: inline-block;
}
.contents {
width: 50px;
height: 50px;
background: green;
}
JS
$('.container').click(function() {
var child = $(this).children();
console.log('child ' + child);
$('.main-div').append(child);
});
$('.main-div').click(function(child) {
console.log('child ' + child);
$('.main-div').detach(child);
});
FIDDLE
Set ids for the containers
<div class="main-div">
</div>
<div class="container" id="container1">
<div class="contents">
A
</div>
</div>
<div class="container" id="container2">
<div class="contents">
B
</div>
</div>
And set a data attribute for the children on click to identify the parent element.
$(function() {
$('.container').click(function() {
var child = $(this).children();
child.attr("data-parentcontainer", this.id);
$('.main-div').append(child);
});
$('.main-div').click(function(child) {
var child = $(this).children();
child.appendTo($("#" + child.data("parentcontainer")));
});
});
JSFIDDLE
Use this JS snippet and let me know if it helps
$('.container').click(function() {
console.log('foo');
var child = $(this).html();
console.log(child);
$('.main-div').append(child);
});
$('.main-div').click(function() {
console.log('foo');
var main = $(this).html();
if(main.length != 0) {
$('.main-div').empty();
}
else
console.log('Main div is empty');
});
External DEMO
You can use .detach() and .appendTo(), but along with that you have to keep some identification to know from that .contents div was picked up. So I am making use of data-address attribute for the parent of picked .contents so as to attach it back there. See inline comments for detailed explanation on what will happen with the code.
$('.main-div').on('click', function(e) {
var elem = $(e.target); //capture click event on .main-div
if (elem.hasClass('contents')) { //check if click was on .contents div
var text = elem.text().trim(); //if yes then get its text
elem.detach();//detach the element
elem.appendTo($('div[data-address=' + text + ']')); //attach it based on attribute selector of jquery
}
});
$('.contents').on('click', function() {
var elem = $(this);//get the element
elem.closest('.container').attr('data-address', elem.text().trim())
//add or update data-address attribute of its closest parent i.e. .container
elem.detach();//detach the element
elem.appendTo($('.main-div')); //append it to .main-div
})
.main-div {
width: 200px;
height: 200px;
background: yellow;
cursor: pointer;
}
.container {
width: 150px;
height: 150px;
border: 2px solid purple;
}
.contents {
width: 50px;
height: 50px;
background: green;
position: relative;
padding: 10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="main-div">
</div>
<div class="container">
<div class="contents">
A
</div>
</div>
<div class="container">
<div class="contents">
B
</div>
</div>
You need to add some uniqueness on the div that have class container, you can add a class or id so that when reinserting back to the original div we can identify the div.
i don't think is there other solution to reinsert back to the original div, whenever we identify both div uniquely.
please change your html structure so that we can manipulate through jquery.
I'm building a simple one page app using Polymer. I have created a custom element that contains the Polymer-drag-drop demo. The action of dragging and creating a div works fine, the event object's relatedTarget property holds a reference to the correct drop div. The problem is the srcElement and target property both hold references to the shadowRoot parent polymer element, in this case "workspace-drop".
EDIT:
Logging event.currentTarget on fire also contains a reference to the parentDiv holding the colored children. <div flex horizontal style="border: 1px dotted silver;">
Code is as follows (pretty much the demo but in a polymer element):
<link rel="import" href="/components/polymer/polymer.html">
<script src="/components/webcomponentsjs/webcomponents.js">
</script>
<link rel="import" href="/components/core-drag-drop/core-drag-drop.html">
<polymer-element name="workspace-drop">
<template>
<style>
html {
font-family: 'Helvetica Neue', 'Roboto', 'Arial', sans-serif;
}
body {
height: 100vh;
margin: 0;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
}
.box {
display: inline-block;
width: 100px;
height: 100px;
margin: 16px;
}
.dropped {
position: absolute;
border: 1px solid black;
width: 5px;
height: 5px;
}
</style>
<div flex horizontal style="border: 1px dotted silver;">
<core-drag-drop></core-drag-drop>
<div class="box" style="background-color: lightblue;" draggable="false"></div>
<div class="box" style="background-color: orange;" draggable="false"></div>
<div class="box" style="background-color: lightgreen;" draggable="false"></div>
<div id="hello">Hello World</div>
</div>
<div id="drop" hash="test" class="box" style="border: 3px solid silver; position: relative; width: 300px; height: 300px;" draggable="false"></div>
</template>
<script>
(function(){
addEventListener('drag-start', function(e) {
var dragInfo = e.detail;
// flaw #2: e vs dragInfo.event
console.log(e.detail);
var color = dragInfo.event.target.style.backgroundColor;
dragInfo.avatar.style.cssText = 'border: 3px solid ' + color + '; width: 32px; height: 32px; border-radius: 32px; background-color: whitesmoke';
dragInfo.drag = function() {};
dragInfo.drop = drop;
});
//
function drop(dragInfo) {
var color = dragInfo.avatar.style.borderColor;
var dropTarget = dragInfo.event.relatedTarget;
if (color && dropTarget.id === 'drop') {
var f = dragInfo.framed;
var d = document.createElement('div');
d.className = 'dropped';
d.style.left = f.x - 4 + 'px';
d.style.top = f.y - 4 + 'px';
d.style.backgroundColor = color;
dropTarget.appendChild(d);
dropTarget.style.backgroundColor = color;
}
}
Polymer({
ready: function(){
}
});
})();
</script>
</polymer-element>
Any assistance is appreciated!
Figured it out. It is related to this question.
When loggin an event object, currentTarget is null, but when logging event.currentTarget it logs a value. Why is that?
Logging the event after the drag action has completed returns a reference to the object in its completed state. Logging the specific event.target property on drag-start gave reference to the correct object, on start.