Polymer issues with contenteditable, execCommand, and insertunorderedlist - javascript

I'm writing a very basic WYSIWYG rich editor using Polymer 2.0 and contenteditable attribute of a div but experiencing issues with document.execCommand and executing the command insertunorderedlist. If you select and highlight the text you want to insert an unordered list and click button then it either fails to work correctly using Chrome (latest version) or if using Safari (latest version High Sierra), just hangs. If you try this outside of Polymer (plain old html and javascript) it works fine. Any ideas how to get this working with Polymer 2.0? Here's my code:
<link rel="import" href="../../bower_components/polymer/polymer-element.html">
<dom-module id="polymerbasic-app">
<template>
<style>
:host {
display: block;
}
</style>
<button on-click="_insertunorderedlist" type="button">Insert Unordered List</button>
<div id="textBox" contenteditable="true">
Bullet One
<br> Bullet Two
<br> Bullet Three
</div>
</template>
<script>
/**
* #customElement
* #polymer
*/
class PolymerbasicApp extends Polymer.Element {
static get is() { return 'polymerbasic-app'; }
static get properties() {
return {
prop1: {
type: String,
value: 'polymerbasic-app'
}
};
}
_insertunorderedlist() {
document.execCommand("insertunorderedlist", false, null); this.$.textBox.focus();
}
}
window.customElements.define(PolymerbasicApp.is, PolymerbasicApp);
</script>
</dom-module>
And index.html:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, minimum-scale=1, initial-scale=1, user-scalable=yes">
<title>polymerbasic</title>
<meta name="description" content="polymerbasic description">
<link rel="manifest" href="/manifest.json">
<script src="/bower_components/webcomponentsjs/webcomponents-loader.js"></script>
<link rel="import" href="/src/polymerbasic-app/polymerbasic-app.html">
</head>
<body>
<polymerbasic-app></polymerbasic-app>
</body>
</html>

Related

how to get jstree instance from iframe source?

I have prepare 2 tree view in separate iframe using jstree. The right tree view should control the left tree view. When user click one one the list in right tree view, the respective item folder will open and selected on left tree view. I can make it happen using div in single page. I control the left tree view using instance of left tree view in right jstree div var instance = $('#left').jstree(true);.
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js"></script>
<!doctype html>
<html>
<head>
<script src="jquery/jquery-2.2.3.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.11/jstree.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jstree/3.3.11/themes/default/style.min.css" />
<meta charset="UTF-8">
<title>jstree basic demos</title>
<style>
html { margin:0; padding:0; font-size:62.5%; }
body { max-width:800px; min-width:300px; margin:0 auto; padding:20px 10px; font-size:14px; font-size:1.4em; }
h1 { font-size:1.8em; }
.demo { overflow:auto; border:1px solid silver; min-height:100px; }
.flex-container {
display: flex;
}
.flex-child {
flex: 1;
border: 1px solid black;
}
.flex-child:first-child {
margin-right: 20px;
}
</style>
</head>
<body>
<h1>Tree Menu</h1>
<!-- <button id="evts_button">select node with id 1</button> <em>either click the button or a node in the tree</em>-->
<div class="flex-container">
<div class="flex-child magenta">
<div id="left" class="demo">
</div>
</div>
<div class="flex-child green">
<div id="List">
</div>
</div>
</div>
<script>
$('#left')
.jstree({
'core' : {
'multiple' : false,
'data' : [
{
"text":"A","id":"A","children":[
{"text":"Australia","id":"Aus"},
{"text":"America","id":"Ame"}
]
},
{
"text":"B","id":"B","children":[
{"text":"Beirut","id":"Bei"},
{"text":"Brunei","id":"Bru"}
]
}
]
}
});
$('#List')
.on("changed.jstree", function(e,data){
if(data.selected.length)
{
$("#left").jstree("close_all");
//console.log(data.selected);
selected_node=data.selected[0];//list-j2_1
console.log(selected_node);
var tm_id = selected_node.replace("j2_", "");//tree
var instance = $('#left').jstree(true);
instance.deselect_all();
instance.select_node(tm_id);
$("#left").jstree("open_all", tm_id);
}
})
.jstree({
'core':{
'multiple':false,
'data':[{"text":"Australia", "id":"Aus"},
{"text":"America", "id":"Ame"},
{"text":"Beirut","id":"Bei"},
{"text":"Brunei", "id":"Bru"}]
}
})
</script>
</body>
</html>
When using iframe, I could not get the instance of left tree view. I want to get left tree view instance in index-10_2.html(right iframe source) to select and open respective node. I had use left=$("#1").contents(); to get the iframe content, var instance=left.find('#left'); to get instance, and instance.select_node(tm_id); to select node. But, error instance.select_node is not a function shown.
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="jquery/jquery-2.2.3.min.js"></script>
<script src="vakata-jstree-4a77e59/dist/jstree.min.js"></script>
<link rel="stylesheet" href="vakata-jstree-4a77e59/dist/themes/default/style.min.css" />
</head>
<body>
<iframe src="index-10_1.html" id="1"></iframe>
<iframe src="index-10_2.html" id="2"></iframe>
</body>
</html>
index-10_1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="jquery/jquery-2.2.3.min.js"></script>
<script src="vakata-jstree-4a77e59/dist/jstree.min.js"></script>
<link rel="stylesheet" href="vakata-jstree-4a77e59/dist/themes/default/style.min.css" />
</head>
<body>
<div class="content demo" id="left"></div>
<script>
$('#left')
.jstree({
'core' : {
'multiple' : false,
'data' : [
{
"text":"A","id":"A","children":[
{"text":"Australia","id":"Aus"},
{"text":"America","id":"Ame"}
]
},
{
"text":"B","id":"B","children":[
{"text":"Beirut","id":"Bei"},
{"text":"Brunei","id":"Bru"}
]
}
]
}
});
</script>
</body>
</html>
index-10_2.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<script src="jquery/jquery-2.2.3.min.js"></script>
<script src="vakata-jstree-4a77e59/dist/jstree.min.js"></script>
<link rel="stylesheet" href="vakata-jstree-4a77e59/dist/themes/default/style.min.css" />
</head>
<body>
<div class="content" id="right"></div>
<script>
$('#right')
.on("changed.jstree", function(e,data){
if(data.selected.length)
{
$("#left").jstree("close_all");
console.log(data.selected);
selected_node=data.selected[0];//list-j2_1
console.log(selected_node);
var tm_id = selected_node.replace("j2_", "");//tree
left=$("#1").contents().find('#left');
instance=left.jstree(true);
instance.select_node(tm_id);
$("#left").jstree("open_all", tm_id);
}
})
.jstree({
'core':{
'multiple':false,
'data':[{"text":"Australia", "id":"Aus"},
{"text":"America", "id":"Ame"},
{"text":"Beirut","id":"Bei"},
{"text":"Brunei", "id":"Bru"}]
}
})
</script>
</body>
</html>
I had used document.getElementById('1').contentWindow.jQuery('#left').jstree(true); to get instance from iframe with id='1'. In order to listen to right iframe(with id='2') if any menu has been clicked, I used document.getElementById('2').contentWindow.jQuery('#right').on("changed.jstree",function(e,data){}). I get the instance of left iframe within this function. By using this instance, I has deselect previous selection, select current selection, and open children of selected menu.
index-12.html
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates and open the template
in the editor.
-->
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="jquery/jquery-2.2.3.min.js"></script>
<script src="vakata-jstree-4a77e59/dist/jstree.min.js"></script>
<link rel="stylesheet" href="vakata-jstree-4a77e59/dist/themes/default/style.min.css" />
</head>
<body>
<iframe src="index-12_1.html" id="1"></iframe>
<iframe src="index-12_2.html" id="2"></iframe>
<script>
sec_frm =document.getElementById('2');//second frame
sec_frm.addEventListener("load",function(){//wait for second frame to load
fst_frm_jstinst=document.getElementById('1').contentWindow.jQuery('#left').jstree(true);//first frame jstree instance
document.getElementById('2').contentWindow.jQuery('#right').on("changed.jstree",function(e,data){
if(data.selected.length){
//close all menu in first frame
document.getElementById('1').contentWindow.jQuery('#left').jstree("close_all");
//get selected menu id from second frame
selected_node=data.selected[0];
//deselect any selected menu on first frame
fst_frm_jstinst.deselect_all();
//select node(country)
fst_frm_jstinst.select_node(selected_node);
document.getElementById('1').contentWindow.jQuery('#left').jstree("open_all",selected_node);
//console.log(selected_node);
}
})
})
</script>
</body>
</html>
index-12_1
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="jquery/jquery-2.2.3.min.js"></script>
<script src="vakata-jstree-4a77e59/dist/jstree.min.js"></script>
<link rel="stylesheet" href="vakata-jstree 4a77e59/dist/themes/default/style.min.css"/>
</head>
<body>
<div class="content demo" id="left"></div>
<script>
$('#left')
.jstree({
'core' : {
'multiple' : false,
'data' : [
{
"text":"A","id":"A","children":[
{"text":"Australia","id":"Aus"},
{"text":"America","id":"Ame"}
]
},
{
"text":"B","id":"B","children":[
{"text":"Beirut","id":"Bei"},
{"text":"Brunei","id":"Bru"}
]
}
]
}
});
</script>
</body>
</html>
index-12_2.html
<!DOCTYPE html>
<!--
To change this license header, choose License Headers in Project Properties.
To change this template file, choose Tools | Templates
and open the template in the editor.
-->
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<script src="jquery/jquery-2.2.3.min.js"></script>
<script src="vakata-jstree-4a77e59/dist/jstree.min.js"></script>
<link rel="stylesheet" href="vakata-jstree-4a77e59/dist/themes/default/style.min.css" />
</head>
<body>
<div class="content" id="right"></div>
<script>
$('#right')
.jstree({
'core':{
'multiple':false,
'data':[{"text":"Australia", "id":"Aus"},
{"text":"America", "id":"Ame"},
{"text":"Beirut","id":"Bei"},
{"text":"Brunei", "id":"Bru"}]
}
})
</script>
</body>
</html>

Using ionic custom elements in standard custom elements

I wonder if someone already run into the following issue:
I am trying to use ion custom elements in standard custom elements, but the ion custom elements do not seem to work properly when used within the shadow root.
I created a small test that shows the problem
both custom elements should render a black button, but only the UsingInnerHtml element works as expected, the UsingShadowRoot renders a transparent button no matter which color value I provide
class UsingInnerHtml extends HTMLElement {
connectedCallback() {
this.innerHTML = `
<ion-button color="dark">Click me</ion-button>
`;
}
}
const template = document.createElement('template');
template.innerHTML = `
<ion-button color="dark">Click me</ion-button>
`;
class UsingShadowRoot extends HTMLElement {
constructor() {
super();
this.attachShadow({ mode: 'open'});
this.shadowRoot.appendChild(template.content.cloneNode(true));
}
}
customElements.define('using-shadow-root', UsingShadowRoot);
customElements.define('using-inner-html', UsingInnerHtml);
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, viewport-fit=cover">
<!-- styles -->
<link href="https://unpkg.com/#ionic/core#latest/css/ionic.bundle.css" rel="stylesheet">
<!-- Libs -->
<script type="module" src="https://unpkg.com/#ionic/core#latest/dist/ionic/ionic.esm.js"></script>
<script nomodule="" src="https://unpkg.com/#ionic/core#latest/dist/ionic/ionic.js"></script>
<script type="module" src="https://unpkg.com/ionicons#latest/dist/ionicons/ionicons.esm.js"></script>
<script nomodule="" src="https://unpkg.com/ionicons#latest/dist/ionicons/ionicons.js"></script>
</head>
<body>
<div>
shadow root
<using-shadow-root></using-shadow-root>
</div>
<div>
inner html
<using-inner-html></using-inner-html>
</div>
</body>
</html>

Polymer simple element

I'm having a hard time understanding how to create Web Components using Polymer. My purpose is just to display a string, an input-text and a button, when the button is clicked; the String is updated with the actual value of the input text.
Here is my first try :
<link rel="import" href="./../bower_components/polymer/polymer.html">
<dom-module id="neito-sidebar">
<template>
<style>
</style>
<label for="test">Name : </label>
<input type="text" name="test" id="test">
<button on-tap="_updateSpan">Valider</button>
<span>[[mot]]</span>
</template>
<script>
Polymer({
is: 'neito-sidebar',
properties: {
mot: String,
notify: true
},
_updateSpan: function()
{
this.mot = $('#test').val();
}
});
</script>
</dom-module>
Am I close to the result or do I have everything wrong ?
Oh I forgot, here the index.html that call my components :
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="import" href="./components/neito-sidebar.html">
<link rel="import" href="./bower_components/polymer/polymer.html">
<link rel="import" href="./bower_components/jquery/dist/jquery.js">
<title>Polymer Element</title>
</head>
<body>
<neito-sidebar></neito-sidebar>
</body>
</html>
And here is the structure of the project :
Actually, if you like to do with Polymer way, it's so easy, and even you don't need any js code either any button. What you input, will be appearing in the span.
<link rel="import" href="./../bower_components/polymer/polymer.html">
<link rel="import" href="./../bower_components/iron-input/iron-input.html">
<dom-module id="neito-sidebar">
<template>
<style></style>
<iron-input bind-value="{{mot}}">
<label for="test">Name : </label>
<input id="test" type="text" value="{{mot::input}}">
</iron-input>
<span>[[mot]]</span>
</template>
<script>
Polymer({is: 'neito-sidebar' });
</script>
</dom-module>
<html>
<head>
<base href="https://polygit.org/polymer+:master/components/">
<link href="polymer/polymer.html" rel="import">
<link rel="import" href="iron-input/iron-input.html">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<style>
:host {
display: block;
height: 100%;
}
span {
color:red;
}
</style>
<iron-input bind-value="{{mot}}">
<label for="test">Name : </label>
<input id="test" type="text" value="{{mot::input}}">
</iron-input>
<br/>
<span>[[mot]]</span>
</template>
<script>
HTMLImports.whenReady(function() {
class XFoo extends Polymer.Element {
static get is() { return 'x-foo'; }
static get properties() { return {
}};
static get observers() { return []}
}
customElements.define(XFoo.is, XFoo);
});
</script>
</dom-module>
</body>
</html>
I don't have the rights/points to comment on the previous solution, but you probably just need to make sure you have the polymer components that HakanC has suggested installed in the root directory of your app:
bower install --save PolymerElements/iron-input

External stylesheet in custom element (no Polymer)

I'm building a custom element. this is my code:
<!DOCTYPE html>
<html>
<template>
<link rel="stylesheet" type="text/css" href="pols-notifier.css">
<div class="body">
<button class="close"></button>
<div class="content"></div>
</div>
</template>
<script>
class PolsNotifier extends HTMLElement {
constructor() {
super();
this.currentDocument = document.currentScript.ownerDocument;
}
connectedCallback() {
const instance = this.currentDocument.querySelector('template').content.cloneNode(true);
this.attachShadow({mode: 'open'}).appendChild(instance);
}
}
window.customElements.define('pols-notifier', PolsNotifier);
</script>
</html>
And the page is:
<!Doctype HTML>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="import" href="http://localhost:8080/assets/pols-notifier/pols-notifier.html">
<body>
<pols-notifier></pols-notifier>
</body>
</html>
The console show an error when try load the stylesheet. The file of custom element and the stylesheet are in /assets/pols-notifier directory in my project but the navigator is looking /pols-notifier.css.
Why is looking there?
Greeting. Thanks.

Polymer core-ajax behaves weird when in new polymer element

I put a core-ajax element in a new polymer element but instead of a response I get an Access Control error. When I use the element alone in my index.html on the same url, I get a regular response. Any idea why this is happening?
Polymer Element:
<link rel="import" href="components/polymer/polymer.html">
<link rel="import" href="components/core-ajax/core-ajax.html">
<polymer-element name="reddit-service" attributes="posts subreddit">
<template>
<style>
:host {
display: block;
}
</style>
<core-ajax
auto
url="http://reddit.com/.json"
on-core-response="{{ajaxResponse}}"
handleAs="json"></core-ajax>
</template>
<script>
Polymer('reddit-service', {
created: function() {
this.posts = [];
},
ajaxResponse: function(event, response) {
console.log(event);
}
});
</script>
</polymer-element>
index.html:
<!DOCTYPE html>
<html>
<head>
<!-- META AND STUFF -->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Polymer Reddit App</title>
<!-- POLYMER -->
<script src="components/platform/platform.js"></script>
<link rel="import" href="components/core-ajax/core-ajax.html">
<link rel="import" href="components/core-header-panel/core-header-panel.html">
<link rel="import" href="components/core-toolbar/core-toolbar.html">
<link rel="import" href="reddit-list.html">
</head>
<body unresolved>
<core-toolbar>Reddit with Polymer</core-toolbar>
<core-ajax
auto
url="http://www.reddit.com/.json"
handleAs="json"></core-ajax>
<script>
function handle(event, response) {
console.log(event);
}
document.addEventListener('core-response', handle, false);
</script>
</body>
</html>
In your custom element you're missing the www subdomain which seems to be required for it to work correctly.

Categories