From 31b1e0d5be0ab1410dcdd07d9cfcd33788e872e2 Mon Sep 17 00:00:00 2001 From: Sasha Firsov Date: Wed, 3 Apr 2024 13:05:22 -0700 Subject: [PATCH] slice to attribute test added --- src/custom-element.js | 41 +++++++++++++++++++++++++++-------- stories/parameters.stories.js | 22 +++++++++++++++++++ test/parameters.test.js | 22 ++++++++++++++++++- 3 files changed, 75 insertions(+), 10 deletions(-) diff --git a/src/custom-element.js b/src/custom-element.js index 987597c..5786747 100644 --- a/src/custom-element.js +++ b/src/custom-element.js @@ -229,11 +229,11 @@ createXsltFromDom( templateNode, S = 'xsl:stylesheet' ) emptyNode(c.firstElementChild).append( createText(c,'{'+select[0]+'}')); emptyNode(c.lastElementChild ).append( createText(c,'{'+select[1]+'}')); p.append(c); - val = c.cloneNode(true); + val = c.cloneNode(true); }else - val=cloneAs(a,'xsl:value-of'); - val.removeAttribute('name'); - a.append(val); + val=cloneAs(a,'xsl:value-of'); + val.removeAttribute('name'); + a.append(val); a.removeAttribute('select'); params.push(p) }); @@ -296,16 +296,24 @@ deepEqual(a, b, O=false) } export function -injectSlice( x, s, data ) +injectSlice( x, s, data, dce ) { + if( s.includes('/') ) + { const it = x.ownerDocument.evaluate(s,x) + , n = it.iterateNext(); + if( n.parentNode.localName ==='attributes') + dce.setAttribute( n.localName, data ); + n.textContent = data; + return + } const isString = typeof data === 'string' ; const createXmlNode = ( tag, t = '' ) => ( e => ((e.append( createText(x, t||''))),e) )(x.ownerDocument.createElement( tag )) const el = isString ? createXmlNode(s, data) : document.adoptNode( xml2dom( Json2Xml( data, s ) ).documentElement); [...x.children].filter( e=>e.localName === s ).map( el=>el.remove() ); - el.data = data - x.append(el); + el.data = data; + x.append(el); } function forEach$( el, css, cb){ @@ -401,6 +409,18 @@ export function assureUID(n,attr) n.setAttribute(attr, crypto.randomUUID()); return n.getAttribute(attr) } +export const xPath = (x,root)=>{ + let ret = ''; + const it = root.ownerDocument.evaluate(x, root); + let thisNode = it.iterateNext(); + + while (thisNode) { + console.log(thisNode.textContent); + ret+= thisNode.textContent; + thisNode = it.iterateNext(); + } + return ret +} export const xslTags = 'stylesheet,transform,import,include,strip-space,preserve-space,output,key,decimal-format,namespace-alias,template,value-of,copy-of,number,apply-templates,apply-imports,for-each,sort,if,choose,when,otherwise,attribute-set,call-template,with-param,variable,param,text,processing-instruction,element,attribute,comment,copy,message,fallback'.split(','); export const toXsl = (el, defParent) => { const x = create('xsl:'+el.localName); @@ -479,7 +499,8 @@ CustomElement extends HTMLElement this.innerHTML=''; injectData( x, 'attributes' , this.attributes, e => createXmlNode( e.nodeName, e.value ) ); injectData( x, 'dataset', Object.keys( this.dataset ), k => createXmlNode( k, this.dataset[ k ] ) ); - const sliceRoot = injectData( x, 'slice', sliceNames, k => createXmlNode( k, '' ) ); + const sliceRoot = injectData( x, 'slice', sliceNames, k => createXmlNode( k, '' ) ) + , slicePath = x => xPath(x, sliceRoot); this.xml = x; const sliceEvents=[]; @@ -490,7 +511,7 @@ CustomElement extends HTMLElement { const s = attr( ev.target, 'slice'); if( processed[s] ) continue; - injectSlice( sliceRoot, s, 'object' === typeof ev.detail ? {...ev.detail}: ev.detail ); + injectSlice( sliceRoot, s, 'object' === typeof ev.detail ? {...ev.detail}: ev.detail, this ); processed[s] = ev; } Object.keys(processed).length !== 0 && transform(); @@ -533,6 +554,8 @@ CustomElement extends HTMLElement el.addEventListener( attr(el,'slice-update')|| 'change', ()=>changeCb(el) ) if( hasInitValue(el) ) changeCb(el) + else + el.value = slicePath( attr(el,'slice') ) } }); DceElement.observedAttributes.map( a => { diff --git a/stories/parameters.stories.js b/stories/parameters.stories.js index 1b304ab..6b6dc63 100644 --- a/stories/parameters.stories.js +++ b/stories/parameters.stories.js @@ -55,3 +55,25 @@ AttributeChange.args = ` }; + + +function TemplateSlice( { title } ) +{ + return ` +
+ ${ title } + + + +
+ `; +} + +export const AttributeFromSlice = TemplateSlice.bind( {} ); +AttributeFromSlice.args = +{ title: `Slice from input propagated to title attribute. Type on input to see attribute change.` +}; diff --git a/test/parameters.test.js b/test/parameters.test.js index b5f62cf..ec494de 100644 --- a/test/parameters.test.js +++ b/test/parameters.test.js @@ -1,7 +1,13 @@ import {fixture, expect, aTimeout} from '@open-wc/testing'; import '../src/custom-element.js'; -import defaults, { AttributeChange, AttributeDefaults, AttributeObservable, AttributeUse } from "../stories/parameters.stories"; +import defaults, { + AttributeChange, + AttributeDefaults, + AttributeFromSlice, + AttributeObservable, + AttributeUse +} from "../stories/parameters.stories"; const defs = {}; Object.keys(defaults.argTypes).map(k => defs[k] = defaults.argTypes[k].defaultValue); @@ -69,4 +75,18 @@ describe('DCE attributes definition', () => }); + it('slice to attribute', async () => + { + const el = await renderStory(AttributeFromSlice); + + const dce = $('custom-element>*',el); + expect(dce.hasAttribute('title')).to.equal(true); + expect(dce.getAttribute('title')).to.equal('😃'); + const input = $('input',dce); + input.value = "abc"; + input.dispatchEvent(new KeyboardEvent('keyup', {'key': 'c'})); + await aTimeout(10); + expect(dce.getAttribute('title')).to.equal('abc'); + }); + });