Сторонние библиотеки обычно не предназначены для использования с веб-компонентами.
Проблема, с которой вы столкнетесь, заключается в использовании jQuery и плагинов jQuery. При создании веб-компонента вы создаете #document-fragment
в #shadowRoot
компоненте в shadowDOM
. Это означает, что стандартные операторы DOM, которые мы используем для выбора элементов (document.getElementById(...)
), не будут работать для выбора элементов в shadowDOM
. Это потому, что shadowDOM
изолирован от корневого документа. Вот почему вы найдете только примеры простых тегов.
JSONEditor, например, широко использует document.createElement()
.
Я преобразовал ваш HTML / JS в веб-компонент , который не будет работать по причинам, указанным выше . По крайней мере, это покажет вам, как поступить с более сложным примером.
Как видно из примера ниже, внешние компоненты и таблицы стилей легко загружаются в компонент. Синтаксис модуля import
может использоваться вместо создания тегов сценария, но эти библиотеки не поддерживают этот синтаксис.
Вот ключевые движущиеся части:
- Класс ES6, представляющий логику пользовательского элемента
- Ваш HTML был помещен в тег
<template>
, который используется для хранения элементов DOM пользовательского элемента
- Это утверждение, которое делает пользовательский элемент доступным для использования:
customElements.define('my-editor', MyEditor);
- Поместить
<my-editor></my-editor>
в файл HTML
Подробнее см. В комментариях к исходному коду.
class MyEditor extends HTMLElement {
constructor () {
super();
this.requiredScripts = [
'https://ajax.googleapis.com/ajax/libs/jquery/3.4.0/jquery.min.js',
'https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js',
'https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.32.5/jsoneditor.js',
'https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2014-11-29/FileSaver.min.js',
];
// Grab a reference to the custom element
let template = document.getElementById('my-custom-editor');
// Get the #document-fragment
let templateContent = template.content;
// Place the template from the Web Component in to the active DOM
this.attachShadow({ mode: 'open' }).appendChild(templateContent.cloneNode(true));
}
// lifecycle hook that fires when custom element is placed into DOM
connectedCallback () {
// load required external resources
this.loadScripts(0);
}
loadScripts (idx) {
const tag = document.createElement('script');
tag.src = this.requiredScripts[idx];
tag.onload = () => {
if (idx < this.requiredScripts.length - 1) {
// when a script has finished, go get the next one
this.loadScripts(++idx);
} else {
// Once all the script files are loaded, initialize the working parts of the component
this.initEditor();
}
}
tag.onload.bind(this);
document.head.appendChild(tag);
}
initEditor () {
// Need a reference to the #document-fragment
// Every instance of "document" in this method has been replaced with "component"
const component = document.getElementById('my-custom-editor').content;
const options = {
mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
onError: function (err) {
alert(err.toString());
},
onModeChange: function (newMode, oldMode) {
console.log('Mode switched from', oldMode, 'to', newMode);
}
};
// create the editor IN THE compoent (rathar than the DOM)
var editor = new JSONEditor(component.getElementById('jsoneditor'), options);
component.getElementById('saveDocument').onclick = function () {
fname = window.prompt("Save as...");
if (fname.indexOf(".") == -1) {
fname = fname + ".json";
} else {
if (fname.split('.').pop().toLowerCase() == "json") {
} else {
fname = fname.split('.')[0] + ".json";
}
}
var blob = new Blob([editor.getText()], {
type: 'application/json;charset=utf-8'
});
saveAs(blob, fname);
};
}
}
customElements.define('my-editor', MyEditor);
html,
body {
font: 11pt sans-serif;
}
<!DOCTYPE HTML>
<html>
<head>
<title>JSONEditor</title>
<meta charset="utf-8">
<link href="styles.css" rel="stylesheet">
<script defer src="lib/MyEditor.js"></script>
<!-- <script src="app.js"></script> -->
<!-- <script src="worker.js"></script> -->
</head>
<body>
<my-editor></my-editor>
<template id="my-custom-editor">
<link href="https://cdnjs.cloudflare.com/ajax/libs/jsoneditor/5.32.5/jsoneditor.css" rel="stylesheet" type="text/css">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
<style>
#jsoneditor {
width: 700px;
height: 600px;
}
#paste,
#link,
#file {
margin-top: 25px;
align-content: center;
}
</style>
<div class="container-fluid">
<h1 align="center">Load and save JSON documents</h1>
<br><br><br>
<div class="row">
<div class="col">
<div id="jsoneditor"></div>
</div>
<div class="col col-centered">
<div class="row">
<div class="col">
<select id="test" name="form_select" onchange="showDiv(this)">
<option value="paste">paste json</option>
<option value="file">Upload file</option>
<option value="link">use link</option>
</select>
</div>
<div class="col">
<p>
Save a JSON document: <input type="button" id="saveDocument" value="Save"/>
</p>
</div>
</div>
<div class="row">
<div class="col">
<div id="file" style="display: none;" class="col-sm col-centered">
Load a JSON document: <input type="file" id="loadDocument" value="Load"/>
<button class="button" onclick="readFile()">LOAD JSON</button>
</div>
<div id="paste" style="display: none;" class="col-sm col-centered">
<h3>Paste JSON data </h3>
<textarea id="myText" rows="4" cols="50"></textarea>
<button class="button" onclick="loadText()">LOAD JSON</button>
</div>
<div id="link" style="display: none;" class="col-sm col-centered">
<h3>URL</h3>
<input type="text" id="url">
<button class="button" onclick="urlOnclick()">LOAD JSON</button>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
</body>
</html>