How to remove custom element while avoiding detached DOM trees? - dom

I'm using Polymer to create custom elements (web components) and have run into a problem when removing them from the DOM. Say I have an element like this:
<link rel="import" href="../polymer/polymer.html">
<polymer-element name="demo-element">
<template>
<h1 on-tap="{{ titleTap }}">A custom demo element</h1>
</template>
<script>
Polymer('demo-element', {
titleTap: function() { // do something }
});
</script>
</polymer-element>
Then when removing the <demo-element></demo-element> from the DOM I will end up with a detached DOM tree with a reference to the H1 element (according to Chrome Devtools). It seems to me that it's the polymerWrapper that references it.
According to the documentation in Polymer API reference the framework should automatically handle the unbind. Is this not working or am I misunderstanding it?
Is this something that in the future will be handled by the browsers or will we need to depend on frameworks like Polymer to do keep our memory clean? (So what I'm asking is if there are any proposals or standards relating to this)

Related

AEM - data-sly-resource children html

I want to figure out a way to insert HTML inside a <sly data-sly-resource> tag and be able to go inside the component I am retrieving from the resource attribute.
To compare, it would be something like Vue's slots, and React's { this.props.children }.
Example:
Parent Component
<sly data-sly-resource="${'example' # resourceType='path/to/component/structure/example'}">
<h1>Hello World</h1>
</sly>
Example Component
<div id="example-component">
${ variable.getChildrenHTMLCall() } // Does something like this exist?
</div>
Output
<div id="example-component">
<h1>Hello World</h1>
</div>
This functionality does not exist.
You could make a similar functionality by using data-sly-template. But you’d have to pass the HTML sting as a parameter (more specifically option) but that might not be desired or maintainable.
You could use the com.day.cq.contentsync.handler.util.RequestResponseFactory as seen here: http://www.nateyolles.com/blog/2015/10/get-rendered-html-for-an-aem-resource-or-component

Give X3DOM access to <x3d> elements inside Polymer.Element

I want to use x3dom together with my PolymerElements, but if I put the needed x3d tag inside my Polymer.Element, X3Dom states, that no containers are found, because it uses document.getElementsByTagName('X3D');
see here: https://github.com/x3dom/x3dom/blob/652f3d4acd5e9e9f62b3ecdd92dec5e5c8a2fd86/src/Main.js#L25
Is there a way to make dom elements 'public' so that they can be found by libraries like x3dom?
P.S.: A working solution I found is by 'slotting' the element through to the actual destination.
Example:
<body>
<my-custom-element>
<x3d ...> ... </x3d>
</my-customelement>
<script src="x3dom-full.js">
</body>
Works, if I design my Element like this:
<dom-module id="my-custom-element">
<template>
<style></style>
<slot></slot>
</template>
</dom-module>
In case I design my element like this:
<dom-module id="my-custom-element">
<template>
<style></style>
<x3d></x3d>
</template>
</dom-module>
x3dom cannot find it, even if the script tag for x3dom-full.js lies inside the template tag.
The reason I do not prefer the slot tags is that I want to hide the x3dom functionality inside my custom element.

New to jquery. Starts with selector breaks the code. what's is wrong?

Thanks for the help. I'm trying to use a jQuery selector to watch for a click on a group of elements, that start with particular characters. I have come up with the following code, but I must be missing something. If I hard code the ID (ie. $("#test_1")...), the code works:
<body>
<div id="content">
<div id="parentcontainer">
<div id="test_1"></div>
</div>
</div>
</body>
<script>
$(window).load(function(){
$("#statusbar").text("Ready");
$("#parentcontainer").click(function(){alert("parent clicked");});
$("#btnaddelement").click(function(){alert("Add Button Clicked");});
$("[name^='test_']").click(function(e){e.stopPropagation();
alert("Child Clicked");});
});
</script>
You are selecting on $("[name^='test_']") which will give you elements who have a name attribute that start with test_. You need to select on $("[id^='test_']") for elements with an id that start with test_. That is one example of what you are getting with your hard-coded success of $('#test_1') -- an element whose id attribute is test_1.
Also, be aware if you are not already that xpath is the language used for selectors, so you can do all kinds of incredible selection if you become familiar with it.
Yes, you missed something. Change the div's attribute id to name will work
<div name="test_1"></div>
Actually, class was used more frequently.
And there are an opinion I want to improve the code.
Try to use the jquery's $(document).ready instead of DOM's load. Because load will wait for all the sources to be loaded compeletely before the js code can be executed, for example, all the photos are downloading ok.
I hope this help!

How to navigate DOM from Wicket

I wonder if it is possible to modify the HTML code of the parent of a wicket component in the Java code to modify its attribute without making it a component in wicket. For example, I would like to add active to the li tag from Java.
<li>
<a wicket:id="home" href="#">
<i class="icon-home"></i>
<span>Home</span>
</a>
</li>
and the say add an Attribute to that parent without referencing it in code as a component.
I don't think this is possible, it would be completely against the modular nature of Wicket. (Not to mention the fact that pages are actually rendered as a stream, there's no DOM tree built.)
Components in Wicket shouldn't depend on what's outside of them. What if you want to change the logic of active/inactive controls? Or, in a more likely scenario, you just want to change the markup. Or if you just want to unit test your component without any surrounding markup.
Wicket was designed to avoid these "spooky actions at a distance", to create components that are genuinely testable on their own.
You need a component that encapsulates the entire list, which keeps track of which of its items is active (via its model). It might seem at first like a lot of work but when you look at the result, you'll realise how much easier it is to understand what's going on.
You can do it using javascript. In this example I overrided the renderHead() of the link, but it can also be done with a Behavior.
public class TestPage extends WebPage {
public TestPage(final PageParameters parameters) {
super(parameters);
add(new AjaxLink<Void>("link") {
boolean active = false;
#Override
public void onClick(AjaxRequestTarget target) {
active = !active;
target.add(this);
}
#Override
public void renderHead(IHeaderResponse response) {
super.renderHead(response);
String addOrRemove = (active) ? ".addClass('active')" : ".removeClass('active')";
response.render(OnDomReadyHeaderItem.forScript("$('#" + getMarkupId() + "').parent('li')" + addOrRemove + ";"));
}
});
}
}
<!DOCTYPE html>
<html xmlns:wicket="http://wicket.apache.org">
<head>
<style type="text/css">
li.active {background-color: red;}
</style>
</head>
<body>
<ul>
<li><a wicket:id="link">TOGGLE</a></li>
</ul>
</body>
</html>
Yes, it will couple the code to the markup, but this is not always a problem. If you feel you are copying and pasting this code over and over, consider creating a proper component :)

Using KnockoutJS template within jQuery template

I have a jQuery template, and I would like to use a KnockOutJS template within this.
I cannot make this work as this example illustrates: http://jsfiddle.net/maate/bwmcR/1/.
However, it DOES work when the KnockOutJS template itself is placed outside the scope of the jQuery template as in this example: http://jsfiddle.net/maate/bwmcR/2/.
It seems that the problem is related to the scope of the template data variables (for instance, I can access the ${test} variable within the subTemplate).
Does anyone know how to make this work?
Br. Morten
The first example you have is just not valid. Although you want to create a sub-template it has to be in a separate script tag. You just can't embed templates within each other, you have to create them one after the other.
WRONG:
<script id="superTemplate" type="text/html">
...
<script id="subTemplate" type="text/html">
...
</script>
</script>
RIGHT:
<script id="superTemplate" type="text/html">
...
</script>
<script id="subTemplate" type="text/html">
...
</script>
When you applied the subtemplate on the ul, you defined what data it should be using with the foreach, so you won't be able to read the test as it is not a property on an item.
If you want you can pass it as a templateOption so it will be available on the subtemplate too.
<ul data-bind="template: { name: 'subTemplate', foreach: items, templateOptions: { testValue: 'Value' } }"></ul>
This way it will be available on the subtemplate.
<span data-bind="text: $item.testValue"></span>
Also, I wouldn't use the default jQuery template tags, it is much nicer with data-binding.
<div id="body" data-bind="template:{name: 'superTemplate'}"></div>
It will do the same, more or less, in the end. You can take a look here : http://jsfiddle.net/bwmcR/18/