styling host in custom element using javascript - javascript

I wrote the below code to get a shadow DOM with text and button, both text and button had been styled correctly, while the host background had been styled in a strange way,
the code is:
// Create a new object based of the HTMLElement prototype
var fonixDiv = Object.create(HTMLElement.prototype);
// Set up the element.
fonixDiv.createdCallback = function() {
// Create a Shadow Root
var shadow = this.createShadowRoot();
shadow.innerHTML = '\
<style>\
:host { \
border: 2px dashed red;\
text-align: left;\
font-size: 28px;\
background: blue;\
}\
h3 { color: red; }\
button { color: green; }\
</style>\
<h3>Shadow DOM</h3>\
<button id="d">click</button>\
';
shadow.children.d.addEventListener('click', function(e) {
this.textContent = "you clicked me :(";
shadow.children[1].textContent="Shadow DOM content changed";
host.style.background = "green";
alert("All: button, text and host should be change");
});
};
the output is in the attached.
any help pls.

I was able to solve the issue using css file:
the .html file is:
<fonix-div></fonix-div>
<div id="host1"></div>
the .js file is:
// Create a new object based of the HTMLElement prototype
var fonixDiv = Object.create(HTMLElement.prototype);
// Set up the element.
fonixDiv.createdCallback = function() {
// Create a Shadow Root
var shadow = this.createShadowRoot();
shadow.innerHTML = '<button id="d">click</button>';
shadow.addEventListener('click', function(e) {
console.log('1: '+this.host.dataset.disabled);
this.host.dataset.disabled='true'; // set Attribute to the custom element
});
shadow.children.d.addEventListener('click', function(e) {
this.textContent = "you clicked me :(";
shadow.children[1].textContent="Shadow DOM content changed";
this.disabled=true;
alert("All: button, text and host should be change");
});
};
// Register the new element.
var Xfonix =document.registerElement('fonix-div', {prototype: fonixDiv});
var thehost = document.querySelector('#host1');
thehost.appendChild(new Xfonix());
the .css file is:
body {background: #F7F7F7;}
fonix-div {
display: inline-block;
width: 200px;
height: 200px;
float: left;
margin: 0.5em;
border-radius: 3px;
background: #FFF;
box-shadow: 0 1px 3px rgba(0,0,0,0.25);
font-family: Helvetica, arial, sans-serif;
-webkit-font-smoothing: antialiased;
}
fonix-div:hover, fonix-div[data-disabled='true']:hover {background: red;}
fonix-div:Active {background: green;}
fonix-div[data-disabled='true'] {background: green;}
fonix-div::shadow p{color: blue;}
the output can be seen here:

Related

.last.removeClass() on recently double clicked element

I have this program that allows the user to edit a div when the user double clicks it. I'm trying to only make the most recent double clicked div have a border. I'm doing this right now with the addClass method, I add the .selceted class with this function:
$(function () {
$("div").dblclick(function (e) {
clickedTD = event.target;
$(clickedTD).find(clickedTD).last.removeClass("selected").addClass("selected");
}
I'm trying to make the last selected div be deleted with this .find(clickedTD).last.removeClass("selected")
So that most recent double clicked div is the only one with the .selected class. But this didn't work and I'm unsure why.
Here is my full code:
var text;
var selectedText;
var blue = document.getElementById("blue");
var blue2 = document.getElementById("blue2");
var elementCounter = 0;
function addElement() {
var classN = event.target.id;
text = document.getElementById("input").value;
// create a new div element and give it a unique id
var newDiv = document.createElement("div");
newDiv.id = 'temp'+elementCounter;
newDiv.classList = "div";
elementCounter++
if (classN == "blue"){
newDiv.classList = "blue"
} else if (classN == "red"){
newDiv.classList = "red"
} else if (classN == "green"){
newDiv.classList = "green"
} else if (classN == "blue2"){
newDiv.classList = "blue2"
}
// and give it some content
var newContent = document.createTextNode(text);
// add the text node to the newly created div
newDiv.appendChild(newContent);
// add the newly created element and its content into the DOM
var currentDiv = document.getElementById("div1");
document.body.insertBefore(newDiv, currentDiv);
$(function() {
var currentlyDragged;
$("div").draggable({
drag: function (e) {
currentlyDragged = e.target.id
selectedText = event.target;
text = $(selectedText).html();
}
});
$(function () {
$("div").dblclick(function (e) {
clickedTD = event.target;
$(clickedTD).find(clickedTD).last.removeClass("selected").addClass("selected");
}
);
});
});
document.getElementById("input").value = " ";
}
#import url('https://fonts.googleapis.com/css2?family=Roboto:wght#300&display=swap');
import { library } from '#fortawesome/fontawesome-svg-core'
import { fas } from '#fortawesome/free-solid-svg-icons'
import { far } from '#fortawesome/free-regular-svg-icons'
import { fab } from '#fortawesome/free-brands-svg-icons'
// Add all icons to the library so you can use it in your page
library.add(fas, far, fab)
h1, body{
font-family: 'Roboto', sans-serif;
}
.selected {
border-style: dashed;
}
div {
text-align: center;
border: 1px solid #d3d3d3;
width: 150px;
height: 30px;
padding: 10px;
cursor: move;
z-index: 10;
background-color: white;
color: blue;
}
divWhite {
text-align: center;
border: 1px solid #d3d3d3;
width: 100px;
padding: 10px;
cursor: move;
z-index: 10;
background-color: white;
color: #fff;
}
.blue {
background: linear-gradient(87deg, #5e72e4 0, #825ee4 100%);
color: white;
}
.red {
background: linear-gradient(87deg, #f5365c 0, #f56036 100%);
color: white;
}
.green {
background: linear-gradient(87deg, #2dce89 0, #2dcecc 100%);
color: white;
}
.blue2 {
background: linear-gradient(87deg, #11cdef 0, #1171ef 100%);
color: white;
}
.white {
background: white;
color: white;
}
button{
font-size: .875rem;
border: none;
border-radius: 3px;
height: 40px;
width: 90px;
text-align: center;
position: relative;
transition: all .15s ease;
letter-spacing: .025em;
text-transform: uppercase;
will-change: transform;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<title>repl.it</title>
<script src="https://code.jquery.com/jquery-3.5.0.js"></script>
<link href="style.css" rel="stylesheet" type="text/css" />
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
</head>
<body style="font-family: 'Roboto', sans-serif;">
<body id="container">
<header id="inputAssignments">
<h1 id="mulAsi">Input Your Assignments for the week:</h1>
<h1 style="display:none" id="oneAsi">Input Your Assignment:</h1>
<input id="input" type="text" value="text">
<button class="blue" id="blue" onclick="addElement()" >Make it Purple</button>
<button class="red" id="red" onclick="addElement()" >Make it Red</button>
<button class="green" id="green" onclick="addElement()" >Make it Green</button>
<button class="blue2" id="blue2" onclick="addElement()" >Make it Blue</button>
<button style="display:none" id="blue2" onclick="addElement();" >input</button>
<h1 height="30px"></h1>
</header>
</header>
<script src="script.js"></script>
</body>
</html>
What you want is ...
div dbclick
Remove selected class from div (actually... div.selcted)
Add selected class to div what you dbclicked.
input[type=text] change
set input[type=text].value to div.selcted.innerHTML
When you use jQuery event,
there are two ways to get $this
Let me show you how to solve this problem.
Regular Function
$('#elementId').on('click', function(){
//1. Remove selected class from div
$('div.selected').removeClass('selected');
//2. Add selected class to $this
const $this = $(this);
$this.addClass('selected')
});
Arrow Function
$('#elementId').on('click', (_event) => {
//1. Remove selected class from div
$('div.selected').removeClass('selected');
//2. Add selected class to $this
const $this = $(_event.currentTarget); // important!
$this.addClass('selected')
});
Finally, Change event of input[type=text]
I will skip arrow function this time.
$('#someInput').on('change', function(){
const value = $(this).val();
$('div.selcted').html(value);
});
DONE!
I recommend you to set id or class to your HTML DOM.
If you set event to ['div', 'input' ...], you will get side effect
Not use div, input
Use #element001(best) or div.myElement001
bye bye

get file object from called window javascript

I am trying to open a window and process the file in the calling JavaScript. I can pass the file name using localStorage but if I return the file I can't get it right.
I can't use this solution due to restrictions of the system I am calling the JavaScript from:
var fileSelector = document.createElement('input');
fileSelector.setAttribute('type', 'file');
fileSelector.click();
Can a file object be passed using localStorage or should I use another method?
My code is:
<!DOCTYPE html>
<html>
<script language="JavaScript">
function testInjectScript2(){
try {
var myhtmltext =
'<input type="file" id="uploadInput3" name=\"files[]" onchange=\'localStorage.setItem("myfile",document.getElementById("uploadInput3").files[0]);\' multiple />';
console.log("myhtmltext="+myhtmltext);
var newWin2 = window.open('',"_blank", "location=200,status=1,scrollbars=1, width=500,height=200");
newWin2.document.body.innerHTML = myhtmltext;
newWin2.addEventListener("unload", function (e) {
if(localStorage.getItem("myfile")) {
var f = localStorage.getItem("myfile");
alert ('in function.f='+f);
alert ('in function.f.name='+(f).name);
localStorage.removeItem("myfile");
}
});
} catch (err) {
alert(err);
}
}
</script>
<body>
<input type="button" text="testInjectScript2" onclick="testInjectScript2()" value="testInjectScript2" />
</body>
</html>
First of all, welcome to SO. If I get you right, you want to upload a file using a new window and get that file using localStorage onto your main page. This is a possible solution. However, please do also note that the maximum size of the localStorage can vary depending on the user-agent (more information here). Therefore it is not recommend to use this method. If you really want to do this, please have a look at the first snippet.
var read = document.getElementById("read-value"), open_win = document.getElementById("open-win"), win, p = document.getElementById("file-set");
open_win.addEventListener("click", function(){
win = window.open("", "", "width=200,height=100");
win.document.write(
'<input id="file-input" type="file"/>' +
'<script>' +
'var input = document.getElementById("file-input");' +
'input.addEventListener("change", function(){window.localStorage.setItem("file", input.files[0]);})'+
'<\/script>'
);
})
read.addEventListener("click", function(){
var file = window.localStorage.getItem("file");
if(file){
p.innerText = "file is set";
}else{
p.innerText = "file is not set";
}
})
<button id="open-win">Open window</button>
<br><br>
<!-- Check if file is set in localStorage -->
<button id="read-value">Check</button>
<p id="file-set" style="margin: 10px 0; font-family: monospace"></p>
<i style="display: block; margin-top: 20px">Note: This only works locally as SO snippets lack the 'allow same origin' flag. i.e. just copy the html and js into a local file to use it.</i>
However, why not use a more elegant solution:
Simply using a modal. When the input value changes you can simply close the modal and get the file value without all the hassle of a localStorage.
// Get the modal, open button and close button
var modal = document.getElementById('modal'),
btn = document.getElementById("open-modal"),
span = document.getElementById("close"),
input = document.getElementById("file-input"),
label = document.getElementById("input-label"), file;
// When the user clicks the button, open the modal
btn.addEventListener("click", function() {
modal.style.display = "block";
})
// When the user clicks on <span> (x), close the modal
span.addEventListener("click", function() {
modal.style.display = "none";
})
input.addEventListener("change", function(){
file = input.files[0];
modal.style.display = "none";
//Change value of the label for nice styling ;)
label.innerHTML = input.files[0].name;
//do something with your value
})
// When the user clicks anywhere outside of the modal, close it
window.addEventListener("click", function(event) {
if (event.target == modal) {
modal.style.display = "none";
}
})
.modal {
display: none; /* Hidden by default */
position: fixed; /* Stay in place */
z-index: 1; /* Sit on top */
padding-top: 10px; /* Location of the box */
left: 0;
top: 0;
width: 100%; /* Full width */
height: 100%; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(0,0,0); /* Fallback color */
background-color: rgba(0,0,0,0.4); /* Black w/ opacity */
}
.modal h2 {
font-family: sans-serif;
font-weight: normal;
}
/* Modal Content */
.modal-content {
background-color: #fefefe;
margin: auto;
padding: 20px;
border: 1px solid #888;
width: 80%;
}
/* The Close Button */
.close {
color: #aaaaaa;
float: right;
font-size: 28px;
font-weight: bold;
}
.close:hover,
.close:focus {
color: #000;
text-decoration: none;
cursor: pointer;
}
/* Input styles, added bonus */
.file-input {
width: 0.1px;
height: 0.1px;
opacity: 0;
overflow: hidden;
position: absolute;
z-index: -1;
}
.file-input + label {
font-size: 1.25em;
font-weight: 700;
padding: 10px 20px;
border: 1px solid #888;
display: inline-block;
cursor: pointer;
font-family: sans-serif;
}
.file-input:focus + label,
.file-input + label:hover {
background-color: #f7f7f7;
}
<!-- Trigger/Open The Modal -->
<button id="open-modal">Open Modal</button>
<!-- The Modal -->
<div id="modal" class="modal">
<!-- Modal content -->
<div class="modal-content">
<span id="close" class="close">×</span>
<h2><i>Upload a file?</i></h3>
<input id="file-input" name="file-input" class="file-input" type="file"/>
<label id="input-label" for="file-input">Upload a file</label>
</div>
</div>
Hope it helps! Let me know!
Cheers!

Polymer drag-drop event object property contains parent srcElement

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.

JavaScript styling of DOM shadow host

I'd written the below code, based on my understanding of this:
The host is not styled!!
var fonixDiv = Object.create(HTMLElement.prototype);
// Set up the element.
fonixDiv.createdCallback = function() {
// Create a Shadow Root
var shadow = this.createShadowRoot();
shadow.innerHTML = '<style>'+
':host { width:200px; height:200px; background: #b0c4de; }'+ // Not working
'p{color: red;}'+ // Working
'</style>'+
'<p>hi</p><button id="d">click</button>';
shadow.children.d.addEventListener('click', function(e) {
this.textContent = "you clicked me :(";
shadow.children[1].textContent="Shadow DOM content changed";
host.style.background = "green"; // working
alert("All: button, text and host should be change");
});
};
// Register the new element.
var Xfonix =document.registerElement('fonix-div', {
prototype: fonixDiv
});
UPDATE
in the html file, I call it as:
<fonix-div></fonix-div>
and as:
<div id='host'></div>
<script>
var host = document.querySelector('#host');
var el = new Xfonix();
host.appendChild(el);
<script>
any help how to style the host element!
fiddle is here
nothing is working for host styling, neither width, nor height nor background :(
I was able to solve the issue using css file:
the .html file is:
<fonix-div></fonix-div>
<div id="host1"></div>
the .js file is:
// Create a new object based of the HTMLElement prototype
var fonixDiv = Object.create(HTMLElement.prototype);
// Set up the element.
fonixDiv.createdCallback = function() {
// Create a Shadow Root
var shadow = this.createShadowRoot();
shadow.innerHTML = '<button id="d">click</button>';
shadow.addEventListener('click', function(e) {
console.log('1: '+this.host.dataset.disabled);
this.host.dataset.disabled='true'; // set Attribute to the custom element
});
shadow.children.d.addEventListener('click', function(e) {
this.textContent = "you clicked me :(";
shadow.children[1].textContent="Shadow DOM content changed";
this.disabled=true;
alert("All: button, text and host should be change");
});
};
// Register the new element.
var Xfonix =document.registerElement('fonix-div', {prototype: fonixDiv});
var thehost = document.querySelector('#host1');
thehost.appendChild(new Xfonix());
the .css file is:
body {background: #F7F7F7;}
fonix-div {
display: inline-block;
width: 200px;
height: 200px;
float: left;
margin: 0.5em;
border-radius: 3px;
background: #FFF;
box-shadow: 0 1px 3px rgba(0,0,0,0.25);
font-family: Helvetica, arial, sans-serif;
-webkit-font-smoothing: antialiased;
}
fonix-div:hover, fonix-div[data-disabled='true']:hover {background: red;}
fonix-div:Active {background: green;}
fonix-div[data-disabled='true'] {background: green;}
fonix-div::shadow p{color: blue;}
the output can be seen here:

Converting DIV element into String

I have a div element that I want to be printed on the page when I click a Create Button.
Thus, when I click create I call a function that has: document.getElementById("createdDiv").textContent = document.querySelector("[data-feed]");
This finds my div element and prints to the page [object HTMLDivElement]
However, when I print the element to the console, I get my div element:
<div data-feed class="feed-element" ... ></div>
I know the console has a toString function that converts the div element into a string but I am not sure how to do this in javascript so I can print the same string to the page. Any suggestions?
You could use outerHTML:
document.getElementById("createdDiv").textContent = document.querySelector("[data-feed]").outerHTML;
document.getElementById("createdDiv").textContent = document.querySelector("[data-feed]").outerHTML;
[data-feed]::before {
content: 'The source element: ';
color: #f00;
}
#createdDiv {
white-space: pre-wrap;
border: 1px solid #000;
padding: 0.5em;
border-radius: 1em;
}
<div data-feed="something"><span>Text in here</span> with <em>various</em> <strong>elements</strong></div>
<div id="createdDiv"></div>
In order to remove HTML from any childNodes, then you could use a function to clone the node, remove the children, and then return only the outerHTML of that specific node:
function tagHTMLOnly(elem) {
var temp = elem.cloneNode();
while (temp.firstChild) {
temp.removeChild(temp.firstChild);
}
return temp.outerHTML;
}
document.getElementById("createdDiv").textContent = tagHTMLOnly(document.querySelector("[data-feed]"));
function tagHTMLOnly(elem) {
var temp = elem.cloneNode();
while (temp.firstChild) {
temp.removeChild(temp.firstChild);
}
return temp.outerHTML;
}
document.getElementById("createdDiv").textContent = tagHTMLOnly(document.querySelector("[data-feed]"));
[data-feed]::before {
content: 'The source element: ';
color: #f00;
}
#createdDiv {
white-space: pre-wrap;
border: 1px solid #000;
padding: 0.5em;
border-radius: 1em;
}
<div data-feed="something"><span>Text in here</span> with <em>various</em> <strong>elements</strong>
</div>
<div id="createdDiv"></div>
References:
Element.outerHTML.

Categories

Resources