How to update shadowRoot/createShadowRoot with the new attachShadow - atom-editor

I'm trying to fix a broken old plugin : https://atom.io/packages/video-player
It doesn't work anymore and there is a warning for shadowRoot and createShadowRoot as depracated.
I commented the old code and updated 3 files with attachShadow. (Trying to do the same thing)
No more Warnings, but it just doesn't work.
//~ this.shadowRoot = this.createShadowRoot();
//~ this.shadowRoot.appendChild(this.videoPlayer);
this.attachShadow({ mode: 'open' }).appendChild(this.videoPlayer);
//~ this.shadowRoot = this.createShadowRoot();
this.attachShadow({ mode: 'open' });
//~ this.shadowRoot = this.createShadowRoot();
//~ this.shadowRoot.appendChild(this.videoPlayer);
this.attachShadow({ mode: 'open' }).appendChild(this.videoPlayer);

Related

Add element outside of an iframe

I have 2 vue projects. In one I am creating a simple component:
<template>
<button #click="importIframe">Click me</button>
</template>
<script>
export default {
name: 'App',
methods: {
importIframe() {
console.log(parent.document)
},
}
</script>
In the other project of vue, import with an iframe the project 01 with a script:
<script src="http://localhost:8081/myiframe.js"></script>
Project 01 is running in localhost:8081 and 02 in 8080. I have a my iframe script which is the one that creates the iframe and imports it into the body.
This is myiframe.js script:
ready(function () {
initIframe()
})
/**
* Auto execute javascript function
* #param callbackFunction
*/
function ready(callbackFunction) {
if (document.readyState != 'loading') callbackFunction()
else document.addEventListener('DOMContentLoaded', callbackFunction)
}
/**
* Initialize iframe
* #return {Promise<void>}
*/
function initIframe() {
// Set url
const baseUrl = 'http://localhost:8081'
// Create div tag
const divContainer = document.createElement('div')
divContainer.setAttribute('id', 'container-iframe')
// Create iframe tag
const iframe = document.createElement('iframe')
iframe.setAttribute('src', baseUrl)
divContainer.appendChild(iframe)
document.body.appendChild(divContainer)
}
What I want to achieve is that by clicking on the button. I should create a new div inside # container-iframe. If I select the iframe container it returns null. And if I select the parent of the iframe with parent.document. It gives me a security error, how can I add an element to the parent of the iframe?
This is a very common issue when you work with cross-domains.
Good news is that we have postMessage to send events between the iframe and the parent.
In the child (iframe button):
<script>
export default {
name: 'App',
methods: {
importIframe() {
parent.postMessage("clicked", "*");
},
}
</script>
Then listen in paranet:
function listenToChild() {
var eventMethod = window.addEventListener
? "addEventListener"
: "attachEvent";
var eventer = window[eventMethod];
var messageEvent = eventMethod === "attachEvent"
? "onmessage"
: "message";
eventer(messageEvent, function (e) {
// if (e.origin !== 'http://the-trusted-iframe-origin.com') return;
if (e.data === "clicked" || e.message === "clicked")
alert('Message from iframe just came!');
// create a new div inside # container-iframe.
console.log(e);
});
}
Then add it to page load (ready function in your case)
More about the postMessage
https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage
https://gist.github.com/cirocosta/9f730967347faf9efb0b

Clarification regarding this.attachShadow({mode: 'open'}) and this.shadowRoot

Regarding native WebComponents:
In the constructor() method at the start of the class it's conventional to attach a shadow DOM tree to the Custom Element and return a reference to its ShadowRoot:
class myCustomElement extends HTMLElement {
constructor() {
super();
const shadowroot = this.attachShadow({mode: 'open'});
}
[... REST OF CODE HERE...]
}
The name of the reference can, of course, be anything.
I have seen:
var shadow = this.attachShadow({mode: 'open'}); (see: Element.attachShadow())
this.root = this.attachShadow({mode: 'open'});
by we could just as easily use:
const myShadowRootzzz = this.attachShadow({mode: 'open'});
However, there already exists Element.shadowRoot which is the ShadowRoot reference.
So why is the syntax
const shadow = this.attachShadow({mode: 'open'});
so commonly used in examples, when simply stating:
this.attachShadow({mode: 'open'});
would be sufficient, since... any time the ShadowRoot needs to be referenced, that reference is, literally:
this.shadowRoot
Why would the WebComponent's ShadowRoot need another arbitrary reference beyond this.shadowRoot ?
Am I missing something important... or can I safely omit such additional references in my own WebComponents?
This is a great example where early code/blogs set the wrong example,
which every Web Component newbie then blindly copy/pastes.
Even the MDN documentation is wrong where it states: Use super() first
This is a perfectly valid constructor:
constructor() {
let myP = document.createElement("p");
let myText = document.createTextNode("my text");
myP.append(myText);
// MDN docs are wrong, you can put code *before* super,
// you just can't reference 'this' *before* it is created
super() // create and return 'this'
.attachShadow({ mode: "open" }) // create and return this.shadowRoot
.append(myP);
}
So a good reason to have a local variable is when one checks for a declarative shadow root.
class MyElement extends HTMLElement {
constructor() {
super();
let internals = this.attachInternals();
let shadow = internals.shadowRoot;
//No declarative shadow root define, so attach
if (!shadow) shadow = this.attachShadow({ mode: 'open' });
shadow.addEventListener('slotchange', this.handleSlotChanged);
}
connectedCallback() {
//Load template & content into shadowroot
}
handleSlotChanged(e) {
//handle changes when slot changes
}
}
customElements.define('my-element', MyElement);
<my-element>
<template>
<p>Nothing happens - no code to generate template</p>
</template>
</my-element>
<my-element>
<template shadowRoot="open">
<p>Automatically generated due to declarative shadow root</p>
</template>
</my-element>
The local "shadow" variable is assigned with "internals.shadowRoot", but that will be null if the template has no declarative shadow root, so assign it the normal way.
Finally, for both scenarios do something with the "shadow" no matter where it came from, e.g. attach some event handlers...
So one can use the this.shadowRoot in the final bit, but if this.shadowRoot is a property, it carries a little extra overhead. Also, is it really the same as "internals.shadowRoot"?

Filereader progress in Vue.js component

I have a component that should to handle the upload file. It holds a bootstrap vue progress component.
I would to handle file loading of filereader.
This is part of vue.js component:
<b-form-file accept=".jpg, .png, .gif, jpeg" v-model="file" size="sm" #change="fileUpload"></b-form-file>
<b-progress :value="progress" :max="maxvalue" show-progress animated></b-progress>
This is my data:
data () {
return {
...
file:null,
progress:0,
maxvalue:100
}
},
This is my code:
fileUpload(ev){
var files = ev.target.files || ev.dataTransfer.files;
const file=files[0];
var reader = new FileReader();
let _vue=this;
reader.onprogress=function(e){
let progress=Math.round((e.loaded / e.total) * 100);
if(progress<100){_vue.progress=progress;}
};
reader.onload = function(event) {
var dataURL = event.target.result;
let image=new Image();
if(file.size>3000000) {
_vue.form.file=null;
alert('Dimensioni file eccessive');
return;
}
image.onload=function(){
_vue.$refs.card.style.maxWidth='250px';
_vue.$refs.card.style.width=`${this.width}px`;
}
image.src=dataURL;
_vue.form.file=dataURL;
};
reader.readAsDataURL(file);
}
If I set an alert, I get the progress values else no.
I noted if I setting two alert sequentially, I see the first alert for every value until the end and then the other one in reverse.
Sorry for my english
I resolved.
The link that resolved my issue:
link
Thanks

How to automatically execute a js event (non-click event) when dotNetCore Blazor loads an index.razor page

Excuse me, everyone, how to enter Index.razor to automatically execute a js event
The carousel plugin used needs to automatically execute the following code
function(){
$("#banner").owlCarousel({
autoPlay : 3000,
paginationSpeed : 1000,
goToFirstSpeed : 2000,
singleItem : true,
autoHeight : true,
navigation: true,
transitionStyle: 'fade'
});
}
Such ineffective no longer should need to load the event in the child page
_Host.cshtml
出现一个错误
Index.razor
出现Object reference not set to an instance of an object.
Just create a JS interop function like that :
wwwroot/scripts/interop.js
window.carousel = {
play: (id, options) => {
$(id).owlCarousel(options);
}
}:
Launch it when your carousel at id is ready in your razor page or component.
Index.razor
#inject IJSRuntime _jsRuntime
<div id="banner"></div>
#code {
protected override async Task OnAfterRenderAsync(bool firstRender)
{
if (!firstRender)
{
return;
}
await _jsRuntime.InvokeVoidAsync("carousel.play", "#banner", new
{
autoPlay = 3000,
paginationSpeed = 1000,
goToFirstSpeed = 2000,
singleItem = true,
autoHeight = true,
navigation = true,
transitionStyle = "fade"
});
}
}
And launch your script in the _Host.cshtml
<script src="scripts/interop.js"></script>

iFrameResizer - readyCallback seems never called

I am trying to use method readyCallback() in iFrameResizer, but it does not seem to work. When I add the callback to parent iframe object, it is never called:
iFrameResize({
log : true,
checkOrigin: false,
minHeight : 800,
maxHeight : 4000,
readyCallback: function(){
// (!) never called
console.log('ready parent callback .. ');
},
messageCallback: function(data){
// works OK
console.log('message callback .. ');
console.log(data);
},
initCallback: function(){
// works OK
window.scrollTo(0,0);
alert("OK initiated");
},
resizedCallback : function(info){
// works OK
console.log(info);
scrollTo(0, info.iframe.offsetTop);
},
heightCalculationMethod : 'taggedElement'
}, '#iframe123');
The iframeResizer.contentWindow.js inside iframe element loads and works OK.
Am I missing something? Thank you.
Turns out that method readyCallback was in wrong place. Here is working setup:
Parent page with iframe element:
iFrameResize({
log : true,
checkOrigin: false,
minHeight : 800,
maxHeight : 4000,
messageCallback: function(data){
console.log('message callback .. ');
console.log(data);
// scroll to top edge of iframe element
scrollTo(0, data.iframe.offsetTop);
},
initCallback: function(){
console.log("OK initiated");
window.scrollTo(0,0);
},
resizedCallback : function(info){
console.log(info);
scrollTo(0, info.iframe.offsetTop);
},
heightCalculationMethod : 'taggedElement'
}, '#iframe123');
Inside iframe element with loaded iframeResizer.contentWindow.js:
// solution 1:
window.iFrameResizer = {
readyCallback: function(){
// scroll parent to top edge of iframe element
window.parentIFrame.scrollToOffset(0,0);
}
}
// solution 2:
window.iFrameResizer = {
readyCallback: function(){
if('parentIFrame' in window){
parentIFrame.sendMessage('Loaded iframe ['+window.parentIFrame.getId()+'].');
}
}
}
// load content window at the end
<script src="/js/iframeResizer.contentWindow.js"></script>

Resources