Polymer2.0- is it possible to get the complete DOM content with Shaow DOM to download? - polymer-2.x

Iam trying to download the custom element after it is being updated with edit option
https://codepen.io/nagasai/pen/PKNeMw
In the above example, I am able download file with x-foo custom element but when I edit the value of it and try to download , I can see only DOM content and without shadow DOM
HTML:
<head>
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-input/paper-input.html">
<link rel="import" href="iron-icons/iron-icons.html">
<link rel="import" href="iron-collapse/iron-collapse.html">
</head>
<body>
<div id="Preview">
<x-foo></x-foo>
</div>
<dom-module id="x-foo">
<template>
<style>
.actionIcons {
position: absolute;
top: 0;
right: 0;
opacity: 0;
background: grey;
}
div.actionIcons iron-icon {
padding: 7px;
}
div.actionIcons iron-icon:hover {
background: lightblue;
}
.actionIcons:hover {
opacity: 1;
}
</style>
Hover Top Right hand hover to edit
<div class="actionIcons">
<iron-icon icon="icons:create" on-click="toggle"></iron-
icon>
<iron-icon icon="icons:content-copy"></iron-icon>
<iron-icon icon="icons:close" onclick="deleteElem(event)">
</iron-icon>
</div>
[[text]]
<paper-input value="{{text::input}}"></paper-input>
<iron-collapse id="collapse">
Enter field name: <paper-input type="text" value="
{{text::input}}" autofocus></paper-input>
</iron-collapse>
</template>
</dom-module>
<button onclick="downloadHtml()"><a id="downloadHtmlElem"
download>Download HTML</a></button>
</body>
JS:
class XFoo extends Polymer.Element {
static get is() { return 'x-foo'; }
static get properties() {
return {};
}
toggle() {
this.$.collapse.toggle();
}
}
customElements.define(XFoo.is, XFoo);
let downloadHtml = () =>{
let a = document.getElementById('downloadHtmlElem')
a.download = "index.html";
a.href = "data:text/text," + document.getElementById("Preview").innerHTML;
}

DOM under the shadow Root, or the shadow DOM, can not be accessed via innerHTML. It is not supposed to be. Just the way it is designed to work.
Unless you are designing your custom element and expose the DOM via Slots.
Or, the published element exposes its DOM somehow.
You could possibly try hacky ways like the one mentioned here
But a direct innerHTML on the parent DIV wouldn't get you what you want.
Also, Leaving the same answer at Your exact same query with references to earlier Stack Overflow discussions on piercing the Shadow DOM

Related

Vue Prism Editor - set tabSize

im currently digging through the github page, but Im unable to figure out how to set the tabSize property on my prism editor, if anyone has any experience and is willing to share it I would greatly appreciate it!
I will answer here as I placed in code snippet for you to play with.
There is a problem on the umd script where it cannot recognise tabSize as a valid props.
Therefore, you can use tab-size to overcome this.
P.S. move tab size to be part of vue data to avoid complaining the type.
Here is the code snippet for you to test it.
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<link rel="stylesheet" href="https://unpkg.com/vue-prism-editor/dist/prismeditor.min.css" />
<link rel="stylesheet" href="https://unpkg.com/prismjs/themes/prism-tomorrow.css" />
<style>
.height-200 {
height: 200px
}
.my-editor {
/* we dont use `language-` classes anymore so thats why we need to add background and text color manually */
background: #2d2d2d;
color: #ccc;
/* you must provide font-family font-size line-height. Example:*/
font-family: Fira code, Fira Mono, Consolas, Menlo, Courier, monospace;
font-size: 14px;
line-height: 1.5;
padding: 5px;
}
/* optional class for removing the outline */
.prism-editor__textarea:focus {
outline: none;
}
</style>
</head>
<body>
<div id="app">
<prism-editor class="my-editor height-200" v-model="code" :highlight="highlighter" line-numbers :tab-size="tabSize">
</prism-editor>
</div>
<script src="https://unpkg.com/vue#2.6.*"></script>
<script src="https://unpkg.com/vue-prism-editor"></script>
<script src="https://unpkg.com/prismjs/prism.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/crypto-js.min.js"></script>
<!-- <script src="./src/index.js"></script> -->
<script>
new Vue({
el: "#app",
data: () => ({
code: "code",
tabSize: 8
}),
methods: {
highlighter(code) {
// js highlight example
return Prism.highlight(code, Prism.languages.js, "js");
}
}
});
</script>
</body>
</html>

b-dropdown-item-button is too long, how can I make it shorter or to wrap the text?

DropDown
I'm using Bootstrap-vue. I need to make the b-dropdown-item-button wrap the text it's showing. How could I do that?
<template>
<b-dropdown menu-class="py-1" text="··· Actions">
<b-dropdown-item-button>Delete</b-dropdown-item-button>
</b-dropdown>
</template>
The dropdown has a min-width andwhite-space: nowrap` set by default, so you need to apply some css to override this.
window.onload = () => {
new Vue({
el: '#app'
})
}
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap/dist/css/bootstrap.min.css" />
<link type="text/css" rel="stylesheet" href="//unpkg.com/bootstrap-vue#latest/dist/bootstrap-vue.min.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.0.4/dist/bootstrap-vue.min.js"></script>
<style>
/* Adding it here since it wasn't working in the snippet CSS */
body { padding: 1rem; }
/* Removes the min-width on the dropdown-menu and sets the width to 100% of the parent */
.wrap-dropdown {
width: 100%;
min-width: 0;
}
/* applies white-space: normal to all tags inside the dropdown-menu */
.wrap-dropdown * {
white-space: normal;
}
</style>
<div id="app">
<b-dd menu-class="py-1 wrap-dropdown" text="··· Actions">
<b-dd-item-btn>Delete</b-dd-item-btn>
<b-dd-item-btn>
This text is really long
</b-dd-item-btn>
</b-dd>
</div>

polymer 2 dom-repeat does not reflect when item is removed

I have a very simple application in Polymer 2. I have a static list of items which is displayed with dom-repeat.
I have a button for delete, on click i could see the item is removed from the list. But the dom-repeat is not refreshed. Its still the old code.
Can someone help how to reflect the changes on the screen:
code snippet is below:
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<link rel="import" href="../../bower_components/iron-list/iron-list.html">
<link rel="import" href="../../bower_components/iron-icons/iron-icons.html">
<link rel="import" href="../../bower_components/app-storage/app-localstorage/app-localstorage-document.html">
<link rel="import" href="../../bower_components/polymer/lib/elements/dom-repeat.html">
<dom-module id="todo-list">
<template>
<style>
:host {
display: block;
}
.ibtn {
float: right;
}
.item {
width: 500px;
}
paper-icon-button {
color: grey;
}
.list-todo {
height: 700px;
text-align: left;
-webkit-text-fill-color: brown;
}
.list-todo ul li {
width: 500px;
font-family: sans-serif;
font-size: 20px;
}
.list-todo .btn-set {
float: right;
}
</style>
<!-- <app-localstorage-document key="app-store" data="{{todos}}"></app-localstorage-document> -->
<div class="list-todo">
<template is="dom-repeat" items="{{todos}}">
<ul>
<li>
<iron-icon icon="icons:arrow-forward"></iron-icon>
{{item}}
<span class="btn-set">
<paper-icon-button icon="create"></paper-icon-button>
<paper-icon-button icon="delete" on-tap="deleteTodo"></paper-icon-button>
<paper-icon-button icon="star"></paper-icon-button>
<span>
</li>
</ul>
</template>
</div>
</template>
<script>
/**
* #customElement
* #polymer
*/
class TodoList extends Polymer.Element {
static get is() { return 'todo-list'; }
static get properties() {
return {
todos: {
type: Object,
value: ["Build the code", "Check Sonar Issues", "Release the APP", "Deploy in Production", "Get Feedback"],
notify: true
}
};
}
populateTodoList() {
return this.todos;
}
deleteTodo(item) {
this.todos.splice(item.model.index, 1);
this.todos.flush;
}
}
window.customElements.define(TodoList.is, TodoList);
</script>
</dom-module>
Javascript splice removes the item from the array, but it does not mean the change is reflected in polymer shadowRoot.
To do this you have to use polymer array mutation methods. See this.
In your case will be:
this.splice('todos', item.model.index, 1);
Also, this.todos.flush; is not needed.
Another thing I detected (not related with this), are you sure you want to have <ul> inside the repeat? This created a bunch of list with just one item inside each list.
I suggest you to do this
<div class="list-todo">
<ul>
<template is="dom-repeat" items="{{todos}}">
<li>
<iron-icon icon="icons:arrow-forward"></iron-icon>
{{item}}
<span class="btn-set">
<paper-icon-button icon="create">create</paper-icon-button>
<paper-icon-button icon="crystal-icons:lens" on-tap="deleteTodo">delete</paper-icon-button>
<paper-icon-button icon="star">star</paper-icon-button>
<span>
</li>
</template>
</ul>
</div>
This way you just create one list.

Dojo grid not scrolling to last item

I'm teaching myself javascript by building a very basic web based chat application.
Chat messages are posted to a web server. An HTML chat Client polls the web server periodically to download any new messages.
The chat messages are displayed using a dojo grid.
My problem is that I can't scroll the grid to the last message. I have tried using scrollToRow but it doesn't work.
The javascript code is here =>
<html>
<head>
<style type="text/css">
#import "./dojoroot/dojo/resources/dojo.css";
#import "./dojoroot/dijit/themes/tundra/tundra.css";
#import "./dojoroot/dojox/grid/resources/Grid.css";
#import "./dojoroot/dojox/grid/resources/tundraGrid.css";
.input {
width: 100%;
padding: 0;
text-align: justify;
}
.dojoxGridHeader {
display: none;
}
</style>
<script language="JavaScript" src="./dojoroot/dojo/dojo.js" djConfig="isDebug: false, parseOnLoad: true">
</script>
<script type="text/Javascript">
dojo.require("dojo.parser");
dojo.require("dojo.dom-style");
dojo.require("dojox.grid.DataGrid");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.layout.ContentPane");
var chatData={items:[]};
var chatStore=new dojo.data.ItemFileWriteStore({data:chatData});
var chatLayout=[[{'name':'Sender','field':'sender','width':'10%'},
{'name':'Message','field':'message','width':'90%'}]];
var chatRow=0;
</script>
</head>
<body>
<div align="center">
<div dojoType="dijit.layout.ContentPane" sizeMin="10" sizeShare="10">
<div id="gridDiv" style="text-align:left; border: 1px solid #aaa; width:98%; height:80%; overflow:auto;">
</div>
</div>
<script type="text/javascript">
var grid=new dojox.grid.DataGrid({id:'grid',
store:chatStore,
structure:chatLayout,
rowSelector:'0px'});
grid.placeAt("gridDiv");
grid.startup();
setInterval(listenToServer,250);
function listenToServer() {
dojo.xhrGet({
url: "http://localhost:8080/ChatProject/ListenToServer",
handleAs: "json",
load: function(data) {
if (data!=null) {
if (data.message!="") {
var myNewItem = {sender: data.sender, message: data.message};
chatRow++;
// Insert the new item into the store:
// (we use store3 from the example above in this example)
chatStore.newItem(myNewItem);
chatStore.save();
var lastRow=grid.store._arrayOfAllItems.length-1;
grid.scrollToRow(lastRow);
}
}
}
});
}
</script>
</body>
</html>
The grid does not scroll down to the last message.
Any help would be much appreciated.
Thanks.
James.
After much experimentation I discovered the following issues:
two separate scroll bars were being created - I assume (although I am not sure) that one scroll bar was associated with the content pane and one with the grid. For the grid I set overflow:hidden to overcome this.
the height:80% parameter was causing the grid to be bigger than the surrounding content pane. I changed this to height:250px.
With these two changes the scrolling started to work (almost).
At this point I encountered this bug in dataGrid => https://bugs.dojotoolkit.org/ticket/10487
At that point I moved on and stopped using dataGrid!

dojo borderlayout show all the content , flicker then redraw correctly

I copied an example from the dojo site using Borderlayout. However, when I load in the browser , the entire data is shown for all the section . Then after a few second the content is refersh and the data is displayed correctly.
here is code that i copied . Thanks for your help
<head>
<link rel="stylesheet" type="text/css" href="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dijit/themes/tundra/tundra.css">
<style type="text/css">
body, html { font-family:helvetica,arial,sans-serif; font-size:90%; }
</style>
<style type="text/css">
html, body { width: 100%; height: 100%; margin: 0; } #borderContainer
{ width: 100%; height: 100%; }
</style>
</head>
<body class="tundra ">
<div dojoType="dijit.layout.BorderContainer" design="sidebar" gutters="true"
liveSplitters="true" id="borderContainer">
<div dojoType="dijit.layout.ContentPane" splitter="true" region="leading"
style="width: 100px;">
Hi
</div>
<div dojoType="dijit.layout.ContentPane" splitter="true" region="center">
Hi, I'm center
</div>
</div>
</body>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"
djConfig="parseOnLoad: true">
</script>
<script type="text/javascript">
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout.BorderContainer");
</script>
<!-- NOTE: the following script tag is not intended for usage in real
world!! it is part of the CodeGlass and you should just remove it when
you use the code -->
<script type="text/javascript">
dojo.addOnLoad(function() {
if (window.pub) {
window.pub();
}
});
</script>
This looks a bit upside down : you should put your javascripts in the head section and load the dojo libraries in first place. That's not your problem though.
What happens is that when the page loads, dojo loads all the modules that you "dojo.require", then parses all your tags containing the attribute "dojoType" and processes them for rendering, and this takes time.
So the flickering that you're seeing is the difference between the page before and after the widgets are parsed.
You should add a preloader div and hide it once the page is parsed (see this example).
This is what it would look like for your example :
<html>
<head>
<title>Preloader example</title>
<!– every Dijit component needs a theme –>
<link rel="stylesheet"
href="http://o.aolcdn.com/dojo/1.4/dijit/themes/soria/soria.css">
<style type="text/css">
#preloader,
body, html {
width:100%; height:100%; margin:0; padding:0;
}
#preloader {
width:100%; height:100%; margin:0; padding:0;
background:#fff
url(’http://search.nj.com/media/images/loading.gif’)
no-repeat center center;
position:absolute;
z-index:999;
}
#borderContainer {
width:100%; height:100%;
}
</style>
<!– load Dojo, and all the required modules –>
<script src="http://o.aolcdn.com/dojo/1.4/dojo/dojo.xd.js"></script>
<script type="text/javascript">
var hideLoader = function(){
dojo.fadeOut({
node:"preloader",
onEnd: function(){
dojo.style("preloader", "display", "none");
}
}).play();
}
dojo.addOnLoad(function(){
// after page load, load more stuff (spinner is already spinning)
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("dojo.parser");
// notice the second onLoad here:
dojo.addOnLoad(function(){
dojo.parser.parse();
hideLoader();
});
});
</script>
</head>
<body class="soria">
<div id="preloader"></div>
<div dojoType="dijit.layout.BorderContainer" id="borderContainer" design="sidebar" gutters="true" liveSplitters="true">
<div dojoType="dijit.layout.ContentPane" splitter="true" region="leading" style="width: 100px;">Hi</div>
<div dojoType="dijit.layout.ContentPane" splitter="true" region="center">I'm Center</div>
</div>
</body>
</html>
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/dojo/1.3/dojo/dojo.xd.js"></script>
if(dojo.isIE){
addEvent(window, 'load', function(event) {
dojo.parser.parse();
});
}else{
dojo.addOnLoad(function(){
dojo.addOnLoad(function(){
dojo.parser.parse();
});
});
}
function addEvent( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){obj['e'+type+fn]( window.event );}
obj.attachEvent( 'on'+type, obj[type+fn] );
} else
obj.addEventListener( type, fn, false );
}
disable parseOnLoad and manually add event to parse widgets for ie.