class CCPInputWidgetController extends HTMLElement {
#data = null;
constructor(){
super()
}
connectedCallback(){
this.#data = JSON.parse(this.getAttribute("input"))
if(this.isChecklist()){
const opts = this.#data.schema.enum.join(",")
this.innerHTML += ``
} else if(this.isEnum()){
const opts = this.#data.schema.enum.join(",")
this.innerHTML += ``
}else if(this.isCode()){
this.innerHTML += ``
}else if(this.isDateTime()){
const t = this.#data.schema.format.toLowerCase() === "datetime" ?
"datetime-local" : this.#data.schema.format.toLowerCase()
this.innerHTML += ``
}else if(this.isFile()){
this.innerHTML += ``
}else if(this.isSecret()){
this.innerHTML += ``
}else{
this.innerHTML += ``
}
}
set value(value){
this.firstElementChild.value = value
}
get value(){
return this.firstElementChild.value.length === 1 ?
this.firstElementChild.value[0] :
this.firstElementChild.value
}
get name(){
return this.firstElementChild.name
}
isChecklist(){
return this.isEnum() && (this.#data.schema.format === "checklist")
}
isEnum(){
return (this.#data.schema.type === "string") && ("enum" in this.#data.schema)
}
isSecret(){
return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) &&
(this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "secret")
}
isCode(){
return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) &&
(this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "code")
}
isFile(){
return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) &&
(this.#data.schema.format != null) &&
(this.#data.schema.format.toLowerCase() === "file")
}
isDateTime(){
return (this.#data.schema.type === "string") &&
("format" in this.#data.schema) &&
(this.#data.schema.format != null) &&
(["date", "time", "datetime"].indexOf(this.#data.schema.format.toLowerCase()) !== -1)
}
}
window.customElements.define('d4s-ccp-input', CCPInputWidgetController);
class CCPBaseInputWidgetController extends HTMLElement{
#rootdoc = null;
#minOccurs = 1;
#maxOccurs = 1;
#description = ""
#title = ""
#name = ""
#default = null
#options = null
#value = null
#readonly = false
//useful to avoid having a custom element for every basic input type
#type = null
#count = 1
constructor(){
super()
this.#rootdoc = this//this.attachShadow({ mode: "open" });
this.#name = this.getAttribute("name")
this.#title = this.getAttribute("title")
this.#description = this.getAttribute("description")
this.#default = this.getAttribute("default")
this.#minOccurs = Number(this.getAttribute("minoccurs") ? this.getAttribute("minoccurs") : 1)
this.#maxOccurs = Number(this.getAttribute("maxoccurs") ? this.getAttribute("maxoccurs") : 1)
this.#readonly = this.getAttribute("readonly") === "true"
// coalesce all basic input types
this.#type = this.getAttribute("type")
// Handle enum case
this.#options = (this.getAttribute("options") ? this.getAttribute("options").split(",") : null)
this.value = Array(Math.max(this.#minOccurs,1)).fill(this.#default)
}
setValue(v){
this.#value = v
this.render()
}
set value(v){
const actual = Array.isArray(v) ? v : [v]
if(actual.length < this.#minOccurs || actual.length > this.#maxOccurs){
throw `Value with length ${v.length} does not respect bounds [${this.minOccurs},${this.maxOccurs}]`
}
this.#value = actual
this.render()
}
get value(){
return this.#value
}
get rootdoc(){
return this.#rootdoc
}
get required(){
return this.#minOccurs > 0
}
get readonly(){
return this.#readonly
}
isIncrementable(){
return this.#value.length < this.#maxOccurs
}
isDecrementable(){
return this.#value.length > this.#minOccurs && this.#value.length > 1
}
get count(){
return this.#count
}
get name(){
return this.#name
}
get title(){
return this.#title
}
get description(){
return this.#description
}
get default(){
return this.#default
}
get options(){
return this.#options
}
set default(v){
this.#default = v
}
get type(){
return this.#type
}
render(){
this.rootdoc.innerHTML = `
`
this.#rootdoc.querySelector("div[name=root]").addEventListener("click", ev=>{
const src = ev.target.getAttribute("name")
if(src === "plus"){
this.#value.push(this.#default)
this.render()
}else if(src === "minus"){
this.#value.pop()
this.render()
}
})
}
}
class CCPSimpleInputWidgetController extends CCPBaseInputWidgetController{
constructor(){
super()
}
connectedCallback(){
this.rootdoc.addEventListener("input", ev=>{
if(ev.target.getAttribute("name") === this.name){
const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.value
}
})
}
content(){
if(this.value.length <= 1){
return ``
}
var out =
this.value.map((c,i)=>{
return `
`
}).join("\n")
return out
}
}
window.customElements.define('d4s-ccp-input-simple', CCPSimpleInputWidgetController);
class CCPEnumInputWidgetController extends CCPBaseInputWidgetController{
constructor(){
super()
}
connectedCallback(){
this.rootdoc.addEventListener("change", ev=>{
if(ev.target.getAttribute("name") === this.name){
const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.value
}
})
}
content(){
const opts = this.options.map(o=>``).join("\n")
if(this.value.length <= 1){
return ``
}
var out =
this.value.map((c,i)=>{
return `
`
}).join("\n")
return out
}
}
window.customElements.define('d4s-ccp-input-enum', CCPEnumInputWidgetController);
class CCPChecklistInputWidgetController extends CCPBaseInputWidgetController{
constructor(){
super()
}
connectedCallback(){
this.rootdoc.addEventListener("change", ev=>{
if(ev.target.getAttribute("name") === this.name){
const index = Number(ev.target.getAttribute("data-index"))
const elems = Array.prototype.slice.call(ev.currentTarget.querySelectorAll(`input[name='${this.name}'][data-index='${index}']`))
this.value[index] = elems.filter(e=>e.checked).map(e=>e.value).join(",")
}
})
}
buildOpts(index, selections){
return this.options.map(o=>`
-1 ? 'checked' : ''}/>
`).join("\n")
}
content(){
if(this.value.length === 1){
const opts = this.buildOpts(0, this.value.length ? this.value[0].split(",") : [])
return `
${opts}
`
}
var out =
this.value.map((c,i)=>{
const opts = this.buildOpts(i, c.split(","))
return `
${opts}
`
}).join("\n")
return out
}
}
window.customElements.define('d4s-ccp-input-checklist', CCPChecklistInputWidgetController);
class CCPTextAreaWidgetController extends CCPBaseInputWidgetController{
constructor(){
super()
}
connectedCallback(){
this.rootdoc.addEventListener("input", ev=>{
if(ev.target.getAttribute("name") === this.name){
const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.value
}
})
}
content(){
if(this.value.length <= 1){
return ``
}
var out =
this.value.map((c,i)=>{
return `
`
}).join("\n")
return out
}
}
window.customElements.define('d4s-ccp-input-textarea', CCPTextAreaWidgetController);
class CCPFileInputWidgetController extends CCPBaseInputWidgetController{
constructor(){
super()
}
connectedCallback(){
this.rootdoc.addEventListener("change", ev=>{
const tgt = ev.target
if(tgt.getAttribute("name") === this.name){
const index = Number(tgt.getAttribute("data-index"))
const file = ev.target.files[0]
if(file.size > 100*1024){
alert("This input allows only small files (100K). Use references instead ")
ev.stopPropagation()
ev.preventDefault()
tgt.value = null
return false
}
const reader = new FileReader()
reader.addEventListener('load', ev=>{
let encoded = ev.target.result.toString().replace(/^data:(.*,)?/, '');
if ((encoded.length % 4) > 0) {
encoded += '='.repeat(4 - (encoded.length % 4));
}
this.value[index] = encoded
this.querySelector("small[name=preview]").textContent = encoded.substr(0,5) + "..." + encoded.substr(encoded.length-5)
})
reader.readAsDataURL(file)
}
})
}
content(){
if(this.value.length <= 1){
const v = this.value.length ? this.value[0] : ''
return `
${v.substr(0,5) + "..." + v.substr(v.length-5)}
`
}
var out =
this.value.map((c,i)=>{
return `
${c.substr(0,5) + "..." + c.substr(s.length-5)}
`
}).join("\n")
return out
}
}
window.customElements.define('d4s-ccp-input-file', CCPFileInputWidgetController);
class CCPSecretInputWidgetController extends CCPBaseInputWidgetController{
constructor(){
super()
}
connectedCallback(){
this.rootdoc.addEventListener("input", ev=>{
if(ev.target.getAttribute("name") === this.name){
const index = Number(ev.target.getAttribute("data-index"))
this.value[index] = ev.target.value
}
})
this.rootdoc.addEventListener("click", ev=>{
if(ev.target.getAttribute("name") === "password_toggle"){
const index = Number(ev.target.getAttribute("data-index"))
const field = this.rootdoc.querySelector(`input[data-index='${index}']`)
if(field.type === "text") field.type="password";
else field.type = "text";
}
})
}
content(){
if(this.value.length <= 1){
return `
👁
`
}
var out =
this.value.map((c,i)=>{
return `
👁
`
}).join("\n")
return out
}
}
window.customElements.define('d4s-ccp-input-secret', CCPSecretInputWidgetController);