I'm building an audio website.
It uses custom components (for the tracklists, the tracks, the track sources, the player..., but I'm stuck on something.
When the user clicks on a track, the track HTML eventually needs to be refreshed - this allows me, among others, to query the database for informations on that track (eg. track sources) that would be too long to load at the initialization.
Thus, I need to replace my track node by the updated HTML.
But I only find documentation about replacing the content of a node (.innerHTML), not the node itself. This doesn't work for me since I need to get the attributes of the new node.
I don't want to delete the old node and add the new one at the same place because I need to keep the reference to the first node.
What I want to achieve (simplified)
JS
<?php
class myCustomEl extends HTMLElement{
constructor() {
super(); //required to be first
}
connectedCallback(){
this.render();
}
disconnectedCallback(){
}
attributeChangedCallback(attrName, oldVal, newVal){
}
adoptedCallback(){
}
static get observedAttributes() {
}
///
///
render(){
}
reload(){
var self = this;
var success = $.Deferred();
/*
Here we would make an ajax request to return the new content
*/
var newContent = '<my-custom expires="XXXX">New Content</my-custom>';
success.resolve();
return success.promise();
}
}
$( document ).ready(function() {
$('my-custom').on('click', '.wpsstm-source-title', function(e) {
var mynode = this;
mynode.reload().then(
function(success_msg){
console.log("RELOADED!");
console.log(mynode); //here I would like to be able to get mynode with its updated content
},
function(error_msg){
console.log(error_msg);
}
);
});
});
window.customElements.define('my-custom', myCustomEl);
HTML
<my-custom expires="XXXX">Old Content</my-custom>
What I actually do
(because I can't get it to work)
- copy the new node .innerHTML to the old node .innerHTML,
- remove all the attributes of the old node,
- copy all the attributes of the new node to the old node.
It seems to work but I think it's quite hackish, and was wondering how I could achieve this differently.
function swapNode(oldNode,newHTML){
//create new node from HTML
var template = document.createElement('template');
newHTML = newHTML.trim(); // Never return a text node of whitespace as the result
template.innerHTML = newHTML;
var newNode = template.content.firstChild;
//check both nodes have the same tag
if (oldNode.tagName !== newNode.tagName){
console.log("wpsstmSwapNode - tags do not match, abord.");
return false;
}
//remove all old attributes
while(oldNode.attributes.length > 0){
oldNode.removeAttribute(oldNode.attributes[0].name);
}
//add new attributes
let attr;
let attributes = Array.prototype.slice.call(newNode.attributes);
while(attr = attributes.pop()) {
oldNode.setAttribute(attr.nodeName, attr.nodeValue);
}
//switch HTML
oldNode.innerHTML = newNode.innerHTML;
return true;
}
I also tried this
var parent = self.parentNode;
var newContent = '<my-custom>NEWCONTENT</my-custom>';
var newNode = $(newContent).get(0);
var oldNode = parent.removeChild(self);
parent.appendChild(newNode);
newNode.appendChild(oldNode);
Thanks !