user16437793
user16437793

Reputation:

How to apply template in onclick method

So i have a xslt file with more than two circles which differentiate through their id. When I click on one circle, I want the other circles to collapse and to move the clicked circle to a specific position. When I click on the circle again, I want all other circles to show again on the right position. How do i do that?

Upvotes: 0

Views: 146

Answers (2)

Michael Kay
Michael Kay

Reputation: 163302

I can suggest three options:

(a) Write Javascript code to make changes to the HTML page when the event occurs (you can still use XSLT to generate the HTML page in the first place).

(b) Write Javascript code to invoke a new XSLT transformation that modifies the HTML page when the event occurs, using the XSLT processor API.

(c) Write the whole application in XSLT 3.0 using Saxon-JS, including the event handling, as suggested in comments by Martin Honnen.

Which of these appeals to you largely depends on whether you're more comfortable (and more productive) writing Javascript or XSLT -- perhaps also with a thought to the future maintainability of the code.

Upvotes: 0

chrwahl
chrwahl

Reputation: 13070

After you have generated the SVG using XSL it is probably better to do all the interactive part using JavaScript and CSS. This could be an example:

var svg = document.getElementById('svg01');

svg.addEventListener('click', e => {
  if (e.target.nodeName == 'circle') {
    svg.querySelectorAll('circle').forEach(c => c.classList.remove('active'));
    e.target.classList.add('active');
    svg.classList.toggle('collaps');
  }
});
svg circle {
  transition: all .5s ease;
}

.collaps circle {
  r: 1px;
  opacity: 5%;
  cx: 1px;
  cy: 1px;
}

.collaps circle.active {
  r: 40px;
  opacity: 100%;
  cx: 50%;
  cy: 50%;
}
<svg xmlns="http://www.w3.org/2000/svg" id="svg01" viewBox="0 0 100 100" height="400">
  <circle cx="20" cy="20" r="5" fill="red"/>
  <circle cx="10" cy="30" r="5" fill="red"/>
  <circle cx="50" cy="20" r="5" fill="red"/>
  <circle cx="80" cy="40" r="5" fill="red"/>
  <circle cx="70" cy="10" r="5" fill="red"/>
</svg>

Update

OP would like to include a text also. So, here I placed the circle and the text in a <g> element. I scale and translate each <g> element. Problem is that you cannot mix SVG tranforms and CSS transforms, so all the initial positions are also done in CSS. Using XSL you could make a <style> element that takes each id from the XML element, something like: <style>g#id-of-element {translate: transform(10px, 50px)} ... </style> as an alternative to all my nth-child selectors. Btw: scaling and translating at the same time is a bit tricky...

var svg = document.getElementById('svg01');

svg.addEventListener('click', e => {
  if (e.target.nodeName == 'circle') {
    let g = e.target.closest('g');
    svg.querySelectorAll('g').forEach(g => g.classList.remove('active'));
    g.classList.add('active');
    svg.classList.toggle('collaps');
  }
});
svg g {
  transition: all .5s ease;
  transform-origin: center;
}

svg g:nth-child(1) {
  transform: translate(20px, 20px);
}

svg g:nth-child(2) {
  transform: translate(10px, 30px);
}

svg g:nth-child(3) {
  transform: translate(50px, 20px);
}

svg g:nth-child(4) {
  transform: translate(80px, 40px);
}

svg g:nth-child(5) {
  transform: translate(70px, 10px);
}

svg.collaps g {
  transform: translate(-25%, -25%) scale(.5);
  opacity: 5%;
}

.collaps g.active {
  transform: scale(8) translate(45%, 45%);
  opacity: 100%;
}
<svg xmlns="http://www.w3.org/2000/svg" id="svg01" viewBox="0 0 100 100" height="400">
  <g>
    <circle cx="5" cy="5" r="5" fill="red" />
    <text transform="translate(5 5)" font-size="4" dominant-baseline="middle" text-anchor="middle" pointer-events="none">Text</text>
  </g>
  <g>
    <circle cx="5" cy="5" r="5" fill="red" />
    <text transform="translate(5 5)" font-size="4" dominant-baseline="middle" text-anchor="middle" pointer-events="none">Text</text>
  </g>
  <g>
    <circle cx="5" cy="5" r="5" fill="red" />
    <text transform="translate(5 5)" font-size="4" dominant-baseline="middle" text-anchor="middle" pointer-events="none">Text</text>
  </g>
  <g>
    <circle cx="5" cy="5" r="5" fill="red" />
    <text transform="translate(5 5)" font-size="4" dominant-baseline="middle" text-anchor="middle" pointer-events="none">Text</text>
  </g>
  <g>
    <circle cx="5" cy="5" r="5" fill="red" />
    <text transform="translate(5 5)" font-size="4" dominant-baseline="middle" text-anchor="middle" pointer-events="none">Text</text>
  </g>
</svg>

Upvotes: 2

Related Questions