Trying to figure out how to create links using createTextNode - javascript

First off I would like to say, the person that originally created this portion of the code is no longer on the team.
We are creating a development tool to Administrate and Develop servers for our game, that has its own programming language.
I'm using JavaFX with WebView to generate the chat area of the development tool to communicate with other developers and staff. However I want it so hen you post a link it actually shows as a link instead of plain text. I have tried things such as AutoLinker with no success. Here is the HTML portion of the webview.
<script src=".././scripts/Autolinker.js"></script>
<script type="text/javascript">
app = null;
const messages = document.getElementById("messages");
function addMessage(message, options) {
const p = document.createElement("p");
const c = message.indexOf(":");
const modifiedMessage = message; //replaceURLWithHTMLLinks(message);
const ridBrackets = options.replace(/[\[\]']/g, "");
const tokenize = ridBrackets.split(",", 2);
const rcChatOptions = tokenize;
const mFontColor = tokenize[rcChatOptions.BFONTCOLOR];
let timeStampFormat = tokenize[rcChatOptions.TIMESTAMP];
if(c > -1) {
const u = document.createElement("span");
const a = document.createElement("a");
u.className = "user";
if(mFontColor != null) {
u.style.color = mFontColor;
} else {
u.style.color = "#00c02b";
}
//Turn plain text links into actual links
u.appendChild(document.createTextNode(Autolinker.link(modifiedMessage.substring(0, c + 1))));
p.appendChild(u);
if(document.selectedfont != null) {
p.style.fontFamily = document.selectedfont;
}
p.appendChild(document.createTextNode(modifiedMessage.substring(c + 1)));
} else {
p.appendChild(document.createTextNode(modifiedMessage));
}
// Append message and scroll to bottom (if at bottom)
const scrollTop = document.body.scrollTop;
const scrolledToBottom = scrollTop + window.innerHeight >= document.body.scrollHeight;
if(scrolledToBottom) {
messages.appendChild(p);
window.scrollTo(document.body.scrollLeft, document.body.scrollHeight - window.innerHeight);
} else {
messages.appendChild(p);
}
messages.style.backgroundColor = "transparent";
}
</script>
I removed portions of the code that I felt was just a distraction.
This what the tool looks like
https://share.getcloudapp.com/kpuNDB4m
this is what it looks like using AutoLinker
https://share.getcloudapp.com/8LunomDL
(So auto linker is doing its job, it just still isn't rending as HyperLinks)

It looks like the TextNode is created after collecting some substring which would be the link. Here's an example of what it would look like if a link was created directly in js then passed to the TextNode.
One thing you can do is place the text inside of an a tag within a paragraph and then convert like so:
var link = document.createElement('link');
link.innerHTML = 'Website: <a href="http://somelink.com" </a>
link.href = 'http://somelink.com';
link.appendChild(document.createTextNode('http://somelink.com'));

After getting pointed in the right direction (By Frank, Thank You) I found a javascript Library that helped me accomplish what I was looking for.
Library
https://github.com/cferdinandi/saferInnerHTML
Here is an example!
https://share.getcloudapp.com/nOuDPnlp
Usage:
saferInnerHTML(message, modifiedMessage, true);
The last param is an option, append or overwrite.
Obviously, I will have to do some CSS work to make them not display as buttons. But it is exactly what I was trying to achieve.

Related

How to add alt and title attributes along with image in quill editor

var range = this.quill.getSelection();
var value = prompt('please copy paste the image url here.');
if(value){
this.quill.insertEmbed(range.index, 'image', value, Quill.sources.USER);
}
I solved the problem of adding images by linking in the quill editor with the api code above. But I couldn't find how to add alt and title properties with the help of api. I can edit it later with the following javascript code, but I need to edit it at the image insertion stage.
if (e.target.tagName=='IMG') {
console.log(e.target.tagName)
var el = e.target;
el.setAttribute("title", "asdasdasd");
}
})
Also, when I add a or tag to the editor, it is surrounded by a p tag and cannot be edited. It puts everything in the p tag and doesn't allow tags like br. How can I solve these problems?
Sorry for the bad english.
There seems to be no easy and elegant way to do it. The API does not allow it (or I have not seen it) and the source code does not seem to be documented.
I propose this code while waiting for a better solution.
It is based on a solution to observe dynamically created elements. I have added the caption of the title and alt attribute.
To get the code to work, you will need to explain the following to your users:
They must write the title and alt in this format wherever they want to insert the image:
%title% A title %alt% An alternative text
Then, they must select that same:
%title% A title %alt% An alternative text
With that text selected they must click the image button and open the image.
Notice, at the moment, you cannot escape "%alt%", so you cannot use the "%alt%" expression within the value of an attribute.
Example:
%title% The title is before %alt% %alt% the %alt% attribute
This causes an unwanted alt attribute.
Paste this code after creating an editor.
BTW, it is only valid for the first editor that exists.
var FER_alt;
var FER_title;
function FER_callback(records) {
records.forEach(function (record) {
var list = record.addedNodes;
var i = list.length - 1;
for ( ; i > -1; i-- ) {
if (list[i].nodeName === 'IMG') {
if(FER_title.length > 0){
list[i].setAttribute('title',FER_title)
}
if(FER_title.length > 0){
list[i].setAttribute('alt',FER_alt)
}
}
}
});
}
var FER_observer = new MutationObserver(FER_callback);
var FER_targetNode = document.querySelector('.ql-editor')
FER_observer.observe(FER_targetNode, {
childList: true,
subtree: true
});
function FER_getTitleAlt(){
var selection = quill.getSelection();
var texto =quill.getText(selection.index,selection.length);
var titleE = texto.search("%alt%")
FER_title = texto.substr(7,titleE-7);
var titleI = titleE + 5
FER_alt = texto.substring(titleI)
}
var FER_imageboton = document.querySelector(".ql-image")
FER_imageboton.addEventListener("click",FER_getTitleAlt)
Instead of insertEmbed you can use getContents and setContents.
let delta = {
ops: [
{
attributes: {
alt: yourAltValue
},
insert: {
image: yourSrcValue
}
}]
};
let existingDelta = this.quill.getContents();
let combinedDelta = existingDelta.concat(delta);
this.quill.setContents(combinedDelta);
Extends Image blot and override the create method
const Image = Quill.import('formats/image');
class ImageBlot extends Image {
static create(value) {
const node = super.create(value);
if (typeof value === 'string') {
node.setAttribute('src', this.sanitize(value));
node.setAttribute('alt', this.sanitize(value).split('/').reverse()[0]);
}
return node;
}
}
Quill.register(ImageBlot);
In this example, we set alt attribute with image's basename

Banner rotating images. Each image when clicked sends to a different URL (vanilla javascript)

I've been given two examples of how to do this but neither is doing both things that I'm looking to do. My website should include:
Rotating Image Banner (3 images), that changes every few seconds
Each image should be clickable and redirect you to a different URL
In our recent lecture, the professor wrote this code on the board and said that this was how you did that. However, it's not working for me.
<html>
<head>
<script language=JAVASCRIPT type=TEXT/JAVASCRIPT>
//I'm not sure when to use '' or ""
//I replaced some of the "picture.jpg" images with links to images. I'm not sure if I used the right syntax.
adImages = new Array("https://i.picsum.photos/id/666/800/200.jpg",
"https://i.picsum.photos/id/420/800/200.jpg",
"https://i.picsum.photos/id/888/800/200.jpg");
adURL = new Array("https://google.com","https://github.com","https://stackoverflow.com");
thisAd = 0;
//length of what?
imgCt = adImages.length;
function rotate()
{
if (document.images)
{
thisAd++;
//Is it better practice to use "==="?
if (thisAd == imgCt)
{
thisAd = 0;
}
document.adBanner.src=adImages[thisAd];
setTimeout("rotate()", 2 * 1000);
}
}
function newLocation()
{
document.location.href = adURL[thisAd];
}
</script>
</head>
//I don't understand what this is at all
<body onload=rotate()>
//Apparently <center> is obsolete?
<center>
<p><font size=4>Rotating Banner <font color=#ff0000>Assignment 6</font> Rotate Party -
Udemy</font>
</p>
<a href="javascript:newLocation()"><IMG height=105 alt="Ad Banner"
src="https://i.picsum.photos/id/666/800/200.jpg" width=610 name=adBanner></a>
</center>
</body>
</html>
Just a heads up. I've been posting my slides from class on Reddit the past couple of weeks and I've received a lot of comments about things being horribly out of date. If you can, please give me examples that are more modern or better practices than what you see me learning. You can find the conversations about my experience learning JavaScript in community college here if you're interested: https://www.reddit.com/user/gettupled/
The second example we were given was a YouTube video that gave the following example. However, it does not include the option of clicking the image and being sent to a URL. I'm not sure if it's common to post HTML, CSS and Javascript code in the body of a message so I'll just attach a codepen unless told otherwise. This code comes from Travesy Media.
https://codepen.io/vitalwheat/pen/QWbEyqN
Thanks everyone. This is my first post here. Hi.
There are many way to implement this. Here is one of the way to do it.
working Demo
(function() {
"use strict";
const imageList = [
"https://i.picsum.photos/id/666/800/200.jpg",
"https://i.picsum.photos/id/420/800/200.jpg",
"https://i.picsum.photos/id/888/800/200.jpg"
];
const urlList = [
"https://google.com",
"https://github.com",
"https://stackoverflow.com"
];
function createRotatingBanner(rotationTime) {
const $adsBanner = document.querySelector(".adBanner");
let $bannerList;
let currentBannerRendered = 0;
function renderBanner() {
Array.from($bannerList).forEach((banner, bannerIndex) => {
banner.className = bannerIndex === currentBannerRendered ? "" : "hide";
});
currentBannerRendered = (currentBannerRendered+1)%$bannerList.length;
}
// creating Banner image and setting them to hide
function createBanner() {
const fragement = new DocumentFragment();
imageList.forEach((image, index) => {
const banner = document.createElement("img");
banner.src = image;
// wrapping image with anchor element
const anchor = document.createElement("a");
anchor.href = urlList[index];
// hide all the banner
anchor.className = "hide"
anchor.appendChild(banner);
fragement.appendChild(anchor);
});
const cloneFragement = [...fragement.children];
$adsBanner.appendChild(fragement);
return cloneFragement;
}
$bannerList = createBanner();
renderBanner();
setInterval(renderBanner, rotationTime);
}
createRotatingBanner(2000);
})();
.hide {
display: none;
}
<div class="adBanner"></div>

Set og:image and twitter:image meta in wordpress articles with javascript

I'm working on a WP website, and I'm pretty new with code, so after I struggled a whole day to make it work, I just gave up, and decided to ask someone.
I used dynamic meta for all open graphs and twitter cards except image.
All the website pages have a container with an article inside; some articles have an image, and some have none. For the ones with no image, I want to use the Company logo.
So I want to use javascript to add og:image and twitter:image to wordpress, but I can't get over one error that says:
document.getElementsByTagName(" ") is not a function
//add image meta tag
addImageMetaTag();
function addImageMetaTag() {
var imgHolder = document.getElementsByTagName("article")[0];
var image = imgHolder.getElementsByTagName("img");
var source;
function getSource() {
if (image.length != 0) {
var source = image[0].getAttribute("src");
} else {
var source = "http://link_to_my_default_image.png";
}
return source;
};
var meta = document.createElement('meta');
meta.setAttribute("property", "og:image");
meta.content = source;
meta.name = "twitter:image";
document.getElementsByTagName('head')[0].appendChild(meta);
};
Gerald, open graphs and twitter cards are used to create the shared snippet, so it's got nothing to do with crawling.
You were right with your other answer, there were two errors: indeed, I used "getSource" instead of "source", but Wordpress still wouldn't find the "article" class, because the content loads after the header, so I had "var content = undefined", so I got the function working by changing it to this:
// add image meta tag
window.addEventListener("load", function() {
addImageMetaTag();
});
function addImageMetaTag() {
var content = document.getElementById("primary");
var images = content.querySelectorAll("img");
var source;
if (images.length != 0) {
var source = images[0].getAttribute("src");
}
else {
var source = "http://link_to_my_default_image.png";
}
var meta = document.createElement('meta');
meta.setAttribute("property","og:image");
meta.content = source;
meta.name = "twitter:image";
document.getElementsByTagName('head')[0].appendChild(meta);
};

How to insert pause in speech synthesis with grammatical hints

I am writing a simple spelling test app using the HTML5 SpeechSynthesis API. The text I would like my app to say is something like the following: "The spelling word is Cat. The cat chased the dog.".
The API tends to race without much of a pause from the first sentence to the second. I wonder if there is a way to insert a bit of a pause between the 2 sentences. I realize I could create 2 separate utterances and use the pause() call. However the code would be simpler and less brittle if I could simply insert grammatical hints.
Normally in spoken English, one tends to pause a little longer between paragraphs. So I inserted a newline character in my text, but there was no noticeable impact.
I also tried using an ellipsis.
Is there any way to do this or am I stuck breaking everything into separate utterances?
Using an exclamation point "!" adds a nice delay for some reason.
You can chain them together with periods to extend the pause.
"Example text! . ! . ! . !"
Split your text using comma (or custom delimiter) and add your own space using a timeout.
Here is a simple example as a proof-of-concept. Extending it, you can customize your text to include hints as to how long to pause.
function speakMessage(message, PAUSE_MS = 500) {
try {
const messageParts = message.split(',')
let currentIndex = 0
const speak = (textToSpeak) => {
const msg = new SpeechSynthesisUtterance();
const voices = window.speechSynthesis.getVoices();
msg.voice = voices[0];
msg.volume = 1; // 0 to 1
msg.rate = 1; // 0.1 to 10
msg.pitch = .1; // 0 to 2
msg.text = textToSpeak;
msg.lang = 'en-US';
msg.onend = function() {
currentIndex++;
if (currentIndex < messageParts.length) {
setTimeout(() => {
speak(messageParts[currentIndex])
}, PAUSE_MS)
}
};
speechSynthesis.speak(msg);
}
speak(messageParts[0])
} catch (e) {
console.error(e)
}
}
function run(pause) {
speakMessage('Testing 1,2,3', pause)
}
<button onclick='run(0)'>Speak No Pause</button>
<button onclick='run(500)'>Speak Pause</button>
<button onclick='run(1000)'>Speak Pause Longer</button>
Just insert
<silence msec="5000" />
in the text for 5 sec waiting (Source).
Disclaimer: This code works only in an appropriate user agent.
// code taken from https://richjenks.com/dev/speechsynthesis/
var utterance = new SpeechSynthesisUtterance(),
speak = document.getElementById("speak"),
text = document.getElementById("text");
// Delay links and events because speechSynthesis is funny
speechSynthesis.getVoices();
setTimeout(function () {
// Add event listeners
var voiceLinks = document.querySelectorAll(".voice");
for (var i = 0; i < voiceLinks.length; i++) {
voiceLinks[i].addEventListener("click", function (event) {
utterance.voice = speechSynthesis.getVoices()[this.dataset.voice];
});
}
}, 100);
// Say text when button is clicked
speak.addEventListener("click", function (event) {
utterance.text = text.value;
speechSynthesis.speak(utterance);
});
<textarea id="text" rows="5" cols="50">Hi <silence msec="2000" /> Flash!</textarea>
<br>
<button id="speak">Speak</button>
I’ve found inserting synthetic pauses using commas to be quite useful (as an making other manipulations). Here’s a little excerpt:
var speech = new SpeechSynthesisUtterance(),
$content = document.querySelector('main').cloneNode(true),
$space = $content.querySelectorAll('pre'),
$pause_before = $content.querySelectorAll('h2, h3, h4, h5, h6, p, li, dt, blockquote, pre, figure, footer'),
$skip = $content.querySelectorAll('aside, .dont_read');
// Don’t read
$skip.forEach(function( $el ){
$el.innerHTML = '';
});
// spacing out content
$space.forEach(function($el){
$el.innerHTML = ' ' + $el.innerHTML.replace(/[\r\n\t]/g, ' ') + ' ';
});
// Synthetic Pauses
$pause_before.forEach(function( $el ){
$el.innerHTML = ' , ' + $el.innerHTML;
});
speech.text = $content.textContent;
The key is to clone the content node first so you can work with it in memory rather than manipulating the actual content. It seems to work pretty well for me and I can control it in the JavaScript code rather than having to modify the page source.

Javascript - How to remove link within links

Let's say a string contains http://google.com. When I linkify the whole string (that has both unlinked URLs and linked URLs, like the one shown above), it will become http://google.com">http://google.com</a>.
Is there a way to revert the incorrect links (which are the ones already linked before linkifying) back to http://google.com?
I found in WordPress, that it uses $ret = preg_replace("#(]+?>|>))]+?>([^>]+?)#i", "$1$3", $ret); (in wp-includes/formatting.php) to accomplish this. Can someone help me to do this in JavaScript?
Have a look at this http://jsfiddle.net/mplungjan/V5Qca/
<script>
function linkify(id,URL) {
var container = document.getElementById(id);
var links = container.getElementsByTagName("a");
if (links.length ==0) {
container.innerHTML=container.innerHTML.link(URL);
return;
}
var nodes = container.childNodes;
for (var i=nodes.length-1;i>=0;--i) {
if (nodes[i].nodeType ==3 && nodes[i].parentNode.nodeName!="A") {
var link = document.createElement("a");
link.href=URL;
link.innerHTML=nodes[i].nodeValue;
container.replaceChild(link, nodes[i]);
}
}
}
window.onload=function() {
linkify("div1","http://www.google.com/");
}
</script>
<div id="div1">
this is a test of replacing text with links with linkified content
</div>

Categories

Resources