web component after page load is getting destroyed - request

I created a custom element(web component) and using webpack will render without any issues but as I include on the working page(which is a wordpress) on render will show up and at the end of the request to hole rendered element is getting destroyed. I do not get any error in console.
the component looks as it follows
import moment from "moment";
import 'moment/min/moment-with-locales'
moment.locale('de');
export class ToursEvents extends HTMLElement {
constructor() {
super();
//this.attachShadow({mode: 'closed'});
}
connectedCallback() {
this.html = this.innerHTML;
}
get data() {
return this._data;
}
set data(tours) {
let times = tours[0]
this._data = tours[0];
this.vendors = tours[1];
let div = document.createElement("div");
div.innerHTML = `
${times.reduce((acc, item) => `${acc}
<div class="bk_day tours-list__slot">
<div class="bk_date tours-list__date">${moment(item.day).format("dddd")}, ${moment(item.day).format("DD.MM.YYYY")}</div>
<ul class="tours-list__vendors">${ this.makeList(item.times) }</ul>
</div>`
, ``)}`;
this.innerHTML = div.innerHTML
//this.shadowRoot.appendChild(div);
}
makeList(times) {
let list = '';
times.map( (time) => {
const eventId = time.event_id;
const vendor = this.vendors[eventId];
let percentageFree = 0, mark = "", availability ="", workload = typeof(WORKLOAD) !== 'undefined' ? WORKLOAD : 0.8;
let tips = '';
list += '<li data-date="' + time.date + '" data-event-id="' + eventId + '" class="' + mark + '">';
list += '<div class="tours-list__time">' + moment(time.date).format('HH.mm') + ' - ' + moment(time.date).format('HH.mm') +'</div>';
if(vendor.title.includes("Discount")) {
tips += '<div><span class="discount">Spar-tipp!</span></div>';
}
list += '<div class="tours-list__title">' + tips + vendor.title + '</div>';
if(time.available_slots != 0) {
list += '<div class=""><button class=""><span class="bk_info_text">Infos/Tickets</span> <span class="icon-down"></span></button></div>'
} else {
list += '<div class="bk_info"><span>Booked</span></div>'
}
list += '</li>';
});
return list
}
showDetails() {
}
}
customElements.define('tours-events', ToursEvents);
How should I debug this issue?

If you run customElements.define('tours-events', class{}); in the console
and you get undefined you know (WordPress?) redirected you to another page.
If you get a DOM exception the Element IS defined
If your Element is not in the DOM (if that is what you mean with 'destroyed')
you have to step through the console-debugger to find the reason when/why it was removed.
Put a debugger; statement in your element's Constructor and take it from there.

Related

How to wrap hashtag and #username with next Link?

I am working on an application where users can create posts and can mention other users and use the #hashtag in the post. Through API call I get the list of post, now the question is how can we wrap hashtags and usernames with next.js Link component so that on clicking on these link user can be navigated to different pages without page refresh.
I am able to wrap this with <a> tag and render the text with dangerouslySetInnerHTML. But this way my page will get refreshed by clicking on the link I don't want off course this behavior.
Here's my code to format the text with <a> tag:
export const formatPostText = (text) => {
let splitText = text.split(' ')
splitText.forEach((word, index) => {
if (word[0] === "#") {
splitText[index] = '<a class="text-cyanBlue" href="/' + word.replace('#', '') + '/in' + '">' + word + '</a>'
} else if (word[0] === "#") {
splitText[index] = '<a class="text-cyanBlue" href="hashtag' + '/' + word.replace('#', '') + '">' + word + '</a>'
}
})
return splitText.join(' ')
}
I do want the same behavior as LinkedIn and Facebook has done it.
Approach: One way I can think of is to use React.createElement but I doubt this is gonna work.
Thanks in advance!!
I implemented similar things in a recent project. I hope this might be helpful.
export const formatText = (text) => {
console.log("text", text)
let content = text.split(/((?:#|#|https?:\/\/[^\s]+)[a-zA-Z]+)/);
let hashtag;
let username;
return content.map((word) => {
if (word.startsWith("#")) {
hashtag = word.replace('#', '')
return <Link href={`/hashtag/${hashtag}`}><a
className="text-cyanBlue/80 hover:text-cyanBlue">{word}</a></Link>;
} else if (word.startsWith("#")) {
username = word.replace('#', '')
return <Link href={`/profile/${username}`}><a
className="text-cyanBlue/80 hover:text-cyanBlue">{word}</a></Link>;
} else if (word.includes("http")) {
return <a target="_blank" href={word} className="text-cyanBlue/80 hover:text-cyanBlue">{word}</a>
} else {
return word;
}
});
}
I used spans with colors here to make example clear:
https://codesandbox.io/s/modest-http-wnp5xq?file=/src/App.js
export default function App() {
const string =
"Hello everyone, me and #ritika are going to be married this month #happy, #marriage";
const getJSX = () => {
// split with capture
const parts = string.split(/((?:#|#)[a-zA-Z]+)/).filter((s) => s.length);
return parts.map((part) => {
if (part.startsWith("#")) {
// if part starts with `#` return `Link` in your case
return <span style={{ color: "red" }}>{part}</span>;
} else if (part.startsWith("#")) {
// if part starts with `#` return other `Link`
return <span style={{ color: "green" }}>{part}</span>;
} else {
// just return string as is
return part;
}
});
};
return <div className="App">{getJSX()}</div>;
}

Property 'form_blocks' does not exist on type 'GanttStatic'

I have isse when I want to implement multi select input in my project react typescript.
Property 'form_blocks' does not exist on type 'GanttStatic'.
how to fix it.
could any one help me please
gantt.form_blocks['multiselect'] = {
render: function(sns) {
var height = (sns.height || '23') + 'px';
var html =
"<div class='gantt_cal_ltext gantt_cal_chosen gantt_cal_multiselect' style='height:" +
height +
";'><select data-placeholder='...' class='chosen-select' multiple>";
if (sns.options) {
for (var i = 0; i < sns.options.length; i++) {
if (sns.unassigned_value !== undefined && sns.options[i].key == sns.unassigned_value) {
continue;
}
html += "<option value='" + sns.options[i].key + "'>" + sns.options[i].label + '</option>';
}
}
html += '</select></div>';
return html;
}
solved use add union any type.

Video chat windows is not display /reactjs with twillio

I have developed a video chat using Reactjs with twillio. In my project I have to develop two sides ,for one side the chat application run smoothly, but in other one the camera is powered on but video stream does not display(local-media not updating and remote-media), i have used the following code from twilio,
import React, { Component } from "react";
import axios from "axios";
import Video from "twilio-video";
export default class VideoComponent extends Component {
constructor(props) {
super(props);
this.activeRoom = null;
this.previewTracks = null;
this.identity = null;
this.roomName = null;
this.roomJoined = this.roomJoined.bind(this);
}
componentDidMount() {
window.addEventListener("beforeunload", this.leaveRoomIfJoined);
this.refs.buttonPreview.onclick = ()=> {
var localTracksPromise = this.previewTracks
? Promise.resolve(this.previewTracks)
: Video.createLocalTracks();
localTracksPromise.then(
(tracks)=> {
window.previewTracks = this.previewTracks = tracks;
var previewContainer = document.getElementById("local-media");
if (!previewContainer.querySelector("video")) {
this.attachTracks(tracks, previewContainer);
}
},
(error)=> {
this.log("Unable to access Camera and Microphon");
}
);
};
axios.get("/token").then(results => {
this.identity = results.data.identity;
this.refs.roomControls.style.display = "block";
// Bind button to join Room.
this.refs.buttonJoin.onclick = ()=>{
this.roomName = this.refs.roomName.value;
if (!this.roomName) {
alert("Please enter a room name.");
return;
}
this.log("Joining room '" + this.roomName + "'...");
var connectOptions = {
name: this.roomName,
logLevel: "debug"
};
if (this.previewTracks) {
connectOptions.tracks = this.previewTracks;
}
// Join the Room with the token from the server and the
// LocalParticipant's Tracks.
Video.connect(results.data.token, connectOptions).then(this.roomJoined, (error)=> {
this.log("Could not connect to Twilio: " + error.message);
});
};
// Bind button to leave Room.
this.refs.buttonLeave.onclick = ()=> {
this.log("Leaving room...");
this.activeRoom.disconnect();
};
});
}
attachTracks(tracks, container) {
tracks.forEach((track)=> {
container.appendChild(track.attach());
});
}
attachParticipantTracks(participant, container) {
var tracks = Array.from(participant.tracks.values());
this.attachTracks(tracks, container);
}
detachTracks(tracks) {
tracks.forEach((track)=> {
track.detach().forEach((detachedElement)=> {
detachedElement.remove();
});
});
}
detachParticipantTracks(participant) {
var tracks = Array.from(participant.tracks.values());
this.detachTracks(tracks);
}
log(message) {
var logDiv = this.refs.log;
logDiv.innerHTML += "<p>> " + message + "</p>";
logDiv.scrollTop = logDiv.scrollHeight;
}
roomJoined(room) {
this.activeRoom = room;
window.room = room.name;
this.log("Joined as '" + this.identity + "'");
this.refs.buttonJoin.style.display = "none";
this.refs.buttonLeave.style.display = "inline";
// Attach LocalParticipant's Tracks, if not already attached.
var previewContainer = this.refs.localMedia;
if (!previewContainer.querySelector("video")) {
this.attachParticipantTracks(room.localParticipant, previewContainer);
}
// Attach the Tracks of the Room's Participants.
room.participants.forEach((participant)=> {
this.log("Already in Room: '" + participant.identity + "'");
var previewContainer = document.getElementById("remote-media");
this.attachParticipantTracks(participant, previewContainer);
});
// When a Participant joins the Room, log the event.
room.on("participantConnected", (participant)=> {
this.log("Joining: '" + participant.identity + "'");
});
// When a Participant adds a Track, attach it to the DOM.
room.on("trackAdded", (track, participant)=> {
this.log(participant.identity + " added track: " + track.kind);
var previewContainer = document.getElementById("remote-media");
this.attachTracks([track], previewContainer);
});
// When a Participant removes a Track, detach it from the DOM.
room.on("trackRemoved", (track, participant)=> {
this.log(participant.identity + " removed track: " + track.kind);
this.detachTracks([track]);
});
// When a Participant leaves the Room, detach its Tracks.
room.on("participantDisconnected", (participant)=> {
this.log("Participant '" + participant.identity + "' left the room");
this.detachParticipantTracks(participant);
});
// Once the LocalParticipant leaves the room, detach the Tracks
// of all Participants, including that of the LocalParticipant.
room.on("disconnected", ()=> {
this.log("Left");
if (this.previewTracks) {
this.previewTracks.forEach((track)=> {
track.stop();
});
}
this.detachParticipantTracks(room.localParticipant);
room.participants.forEach(this.detachParticipantTracks);
this.activeRoom = null;
this.refs.buttonJoin.style.display = "inline";
document.getElementById("button-leave").style.display = "none";
});
}
leaveRoomIfJoined() {
if (this.activeRoom) {
this.activeRoom.disconnect();
}
}
render() {
return (
<div>
<div id="remote-media"></div>
<div id="controls">
<div id="preview">
<p className="instructions">Hello</p>
<div ref="localMedia" id="local-media"></div>
<button ref="buttonPreview" id="button-preview">Preview My Camera</button>
</div>
<div ref="roomControls">
<p className="instructions">Room Name:</p>
<input ref="roomName" id="room-name" type="text" placeholder="Enter a room name" />
<button ref="buttonJoin" id="button-join">Join Room</button>
<button ref="buttonLeave" id="button-leave">Leave Room</button>
</div>
<div ref="log" id="log"></div>
</div>
</div>
);
}
}

Using for loop render some Html elements in React render function

I am trying to render some html using for loop. Every thing work fine but the html prints like a string inside that UL element I dont know what I did wrong pls help me with this. I am new to this React Js thing.
My Script
const Pagination = React.createClass({
getInitialState: function () {
return {
"page": {
"size": 100,
"limit": 30,
"offset": 0,
"number": 1
}
};
},
render: function () {
var html = [];
var i = 0;
var className = '';
var noOfPages = 0;
var number = 1;
var page = this.state.page;
if (page) {
noOfPages = parseInt((page.size / page.limit), 10);
for (i; i < noOfPages; i++) {
className = (className === number) ? 'selected' : '';
html.push('<li key=' + {i} + ' className=""><button className="' + {className} + '">' + {i} + '</button></li>');
}
}
return (
<div className="pagination-sec-wrapper">
<form className="pagination-inner-sec-wrapper" id="pagination-form">
<ul className="">
{html}
</ul>
</form>
</div>
);
}
});
That's because you are pushing string values into your HTML array.
html.push('<span key=' + {i} + ' className=""><button className="' + {className} + '">' + {i} + '</button></span>');
You need to push React components instead.
html.push(<span key={i} className="">
<button className={className}>{i}</button>
</span>);
It's important to remember that even though JSX looks like HTML strings, it's really just syntactic sugar for regular Javascript function calls.
The above JSX is just the same as the following JS.
html.push(React.createElement("span", { key: i, className: "" },
React.createElement("button", { className: className }, i)));

How can I load youtube videos with angularjs?

I am trying to delay loading of youtube videos via javascript code as explained here.
and here is the code for that:
function optimizeYouTubeEmbeds() {
// Get all iframes
var frames = document.getElementsByTagName('iframe');
// Loop through each iframe in the page.
for (var i = 0; i < frames.length; i++) {
// Find out youtube embed iframes.
if (frames[i].src && frames[i].src.length > 0 && frames[i].src.match(/http(s)?:\/\/www\.youtube\.com/)) {
// For Youtube iframe, extract src and id.
var src = frames[i].src;
var p = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
var id = (src.match(p) ? RegExp.$1 : false);
if (id == false) { continue; }
// Get width and height.
var w = frames[i].width;
var h = frames[i].height;
if (src == '' || w == '' || h == '') { continue; }
// Thease are to position the play button centrally.
var pw = Math.ceil(w / 2 - 38.5);
var ph = Math.ceil(h / 2 + 38.5);
// The image+button overlay code.
var code = '<img src="http://i.ytimg.com/vi/' + id + '/hqdefault.jpg" style="" />';
// Replace the iframe with a the image+button code.
var div = document.createElement('div');
div.innerHTML = code;
div = div.firstChild;
frames[i].parentNode.replaceChild(div, frames[i]);
i--;
}
}
}
// Replace preview image of a video with it's iframe.
function LoadYoutubeVidOnPreviewClick(id, w, h) {
var code = '<iframe src="https://www.youtube.com/embed/' + id + '/? autoplay=1&autohide=1&border=0&wmode=opaque&enablejsapi=1" width="' + w + '" height="' + h + '" frameborder=0 allowfullscreen style="border:1px solid #ccc;" ></iframe>';
var iframe = document.createElement('div');
iframe.innerHTML = code;
iframe = iframe.firstChild;
var div = document.getElementById("skipser-youtubevid-" + id);
div.parentNode.replaceChild(iframe, div);
}
This code worked before switching my project to the angular way of doing things.
I initially thought I could just wrap that code in a $scope and call it, but that did not work. Here is my code that retrieves the videos:
$scope.renderHtml = function (html) {
return $sce.trustAsHtml(html);
};
$scope.Videos = [];
$scope.getVideos = function() {
// api call
$http.get('/api/Videos/AllVideos')
.success(function(data) {
$scope.Videos = data;
});
};
$scope.getVideos();
and here is the html tag where it is rendered:
<div ng-repeat="vid in Videos">
<div ng-bind-html="renderHtml(vid.url)"></div>
</div>
The vid.url includes all the iframe tag information etc. What do I need to do to make this work?

Resources