Can I remove parameter from URL generated by video playlist in Elementor - elementor

Elementor Pro has a new widget, video playlist. It appends a parameter to the URL, like so: http://aaronpenton.net/ampcreative/vip/about-vip/?playlist=f68425e&video=b8a9967
This is obviously terrible for SEO and UX. Is there a way to remove the ?playlist=f68425e&video=b8a9967 ?

My brother help me with the next script.
Put a "HTML Elementor Widget" with the following:
<script>
function getURLParameter(name) {
return decodeURI((RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]);
}
function hideURLParams() {
//Parameters to hide (ie ?playlist=value, ?video=value, etc)
var hide = ['playlist','video'];
for(var h in hide) {
if(getURLParameter(h)) {
history.replaceState(null, document.getElementsByTagName("title")[0].innerHTML, window.location.pathname);
}
}
}
window.onload = hideURLParams;
</script>

This should do the trick.
const url = 'http://aaronpenton.net/ampcreative/vip/about-vip/?playlist=f68425e&video=b8a9967'
url.replace(url.split('/')[6], '')
split, well.. splits the string into an array by the /
character.
At index 6 the array contains the ?playlist=f68425e&video=b8a9967 substring which can than be removed (i.e. replaced by the empty string) using replace.
A more general approach to removing the last part of the url might
be to use the array length instead of specifying the index:
const url = 'http://aaronpenton.net/ampcreative/vip/about-vip/?playlist=f68425e&video=b8a9967'
const urlArr = url.split('/')
url.replace(urlArr[urlArr.length - 1], '')
Update:
Another way to do this is using the URL API
const url = new URL('http://aaronpenton.net/ampcreative/vip/about-vip/?playlist=f68425e&video=b8a9967');
const result = url.origin + url.pathname
or in a function:
const removeParameter = u => {
const url = new URL(u);
return url.origin + url.pathname
}
You might have to check the specification for further details (browser support etc)

Related

ReactJs: How to replace html and string template with a component?

I want to manage the content of the page from a content editor where I am getting page content from the API.
Check this screenshot.
I used two different react modules for this react-html-parser and react-string-replace but it is still not working.
Here is my code.
let pageData = '';
pageData = ReactHtmlParser(page.content);
// replacing contact us form with a contact us form component
pageData = reactStringReplace(pageData, '{CONTACT_US_FORM}', (match, i) => (
<ContactUsForm />
));
return <div>{pageData}</div>;
react-html-parser -> It is used to parse HTML tags which are in string format into tree of elements.
react-string-replace -> It is used to replace a string into react a component.
Note: If I use react-html-parser or react-string-replace individually then it works fine but it does not work together.
Any suggestion?
Depends on the expected structure of page.content. If it contains HTML you are right in using react-html-parser, which has a replace option.
import parse from 'html-react-parser';
const macro = '{CONTACT_US_FORM}';
const replaceContactUsForm = (domhandlerNode) => {
if (domhandlerNode.type === 'text' && domhandlerNode.data.includes(macro))
return <ContactUsForm />;
};
// ...
const elements = parse(page.content, { replace: replaceContactUsForm });
return <div>{elements}</div>;
Additionally, If the string {CONTACT_US_FORM} is embedded in text you could use react-string-replace to keep the rest of the text intact:
const replaceContactUsForm = (domhandlerNode) => {
if (domhandlerNode.type === 'text' && domhandlerNode.data.includes(macro))
return <>{reactStringReplace(domhandlerNode.data, macro, () => (<ContactUsForm />))}</>;
};
If page.content does not contain HTML you do not need react-html-parser. But judging from your screenshot some markup is probably contained.

How can I ensure that the end of my custom quiljs parchment doesn't continue the formatting?

I have a custom parchment that looks like:
import { Quill } from 'react-quill';
const Parchment = Quill.import('parchment');
let config = { scope: Parchment.Scope.INLINE };
let AcceptedPredictionClass = new Parchment.Attributor.Class('accepted', 'ql', config);
Quill.register(AcceptedPredictionClass)
and to use it:
const delta = new Delta()
.retain(currentSelection.index)
.delete(predictionLength)
.insert(previousPredictionText, { accepted: 'accepted' })
quill.updateContents(delta)
but the problem is that if I start typing, it keeps the ql-accepted style. I need it to revert back to normal.
How about simply adding one more .insert(' ', {}) after last insert? This should add one normal span after the inserted class.
This is how it will be:
const delta = new Delta()
.retain(currentSelection.index)
.delete(predictionLength)
.insert(previousPredictionText, { accepted: 'accepted' })
.insert(' ', {})
quill.updateContents(delta)
FYI: I haven't tested it yet but the general idea is that the cursor will be inside new span without the added class.

How to use ranges saved to React state - Microsoft Word javascript API?

I am using the Microsoft Word Javascript API. I have used the .search() function to retrieve an array of ranges and then have saved them to state.definitions in my App.js React component state. This part works. When I try to print out the state using console.log(JSON.stringify(this.state.definitions)), I see the ranges that I just saved.
In a separate function, I want to retrieve those ranges and highlight them in a new color. This part does not work. I don't get any errors, but I don't see any highlight changes in the document.
Interestingly, if I try to highlight the ranges BEFORE saving them to state, it works. This makes me think that the ranges that I am retrieving from state are not actually the ranges understood by Word.
Any help would be much appreciated.
var flattenedTerms contains an array of range items that were retrieved from Word a few lines above. This code successfully changes the font
for (var i = 0; i < flattenedTerms.length; i++) {
console.log('flattenedTerms: ', flattenedTerms[i]);
flattenedTerms[i].font.color = 'purple';
flattenedTerms[i].font.highlightColor = 'pink';
flattenedTerms[i].font.bold = true;
}
return context.sync().then(function () {
return resolve(flattenedTerms);
})
})
Now the flattenedTerms array, which contains the range items, has been saved to state.definitions using this.setState. This fails to change the font. All of the console.logs do print.
highlightDefinedTerms = () => {
var self = this;
return Word.run(
function (context) {
var definitions = self.state.definitions;
console.log('Highlighting ', definitions.length, ' terms.');
for (var i = 0; i < definitions.length; i++) {
console.log('Highlighting definition: ', JSON.stringify(definitions[i]));
definitions[i].font.color = 'blue';
definitions[i].font.highlightColor = 'red';
definitions[i].font.bold = true;
}
return context.sync();
}
)
}
You need to pass a first parameter to “Word.run” to specify the object whose context you want to resume.
Word.run(self.state.definitions, function(context) ...)

Convert Quill Delta to HTML

How do I convert Deltas to pure HTML? I'm using Quill as a rich text editor, but I'm not sure how I would display the existing Deltas in a HTML context. Creating multiple Quill instances wouldn't be reasonable, but I couldn't come up with anything better yet.
I did my research, and I didn't find any way to do this.
Not very elegant, but this is how I had to do it.
function quillGetHTML(inputDelta) {
var tempCont = document.createElement("div");
(new Quill(tempCont)).setContents(inputDelta);
return tempCont.getElementsByClassName("ql-editor")[0].innerHTML;
}
Obviously this needs quill.js.
I guess you want the HTML inside it. Its fairly simple.
quill.root.innerHTML
If I've understood you correctly, there's a quill thread of discussion here, with the key information you're after.
I've quoted what should be of most value to you below:
Quill has always used Deltas as a more consistent and easier to use (no parsing)
data structure. There's no reason for Quill to reimplement DOM APIs in
addition to this. quill.root.innerHTML or document.querySelector(".ql-editor").innerHTML works just fine (quill.container.firstChild.innerHTML is a bit more brittle as it depends on child ordering) and the previous getHTML implementation did little more than this.
Simple, solution is here:
https://www.scalablepath.com/blog/using-quill-js-build-wysiwyg-editor-website/
The main code is:
console.log(quill.root.innerHTML);
This is a very common confusion when it comes to Quilljs. The thing is you should NOT retrieve your html just to display it. You should render and display your Quill container just the same way you do when it is an editor. This is one of the major advantages to Quilljs and the ONLY thing you need to do is:
$conf.readOnly = true;
This will remove the toolbar and make the content not editable.
I have accomplished it in the backend using php.
My input is json encoded delta and my output is the html string.
here is the code , if it is of any help to you.This function is still to handle lists though and some other formats but you can always extend those in operate function.
function formatAnswer($answer){
$formattedAnswer = '';
$answer = json_decode($answer,true);
foreach($answer['ops'] as $key=>$element){
if(empty($element['insert']['image'])){
$result = $element['insert'];
if(!empty($element['attributes'])){
foreach($element['attributes'] as $key=>$attribute){
$result = operate($result,$key,$attribute);
}
}
}else{
$image = $element['insert']['image'];
// if you are getting the image as url
if(strpos($image,'http://') !== false || strpos($image,'https://') !== false){
$result = "<img src='".$image."' />";
}else{
//if the image is uploaded
//saving the image somewhere and replacing it with its url
$imageUrl = getImageUrl($image);
$result = "<img src='".$imageUrl."' />";
}
}
$formattedAnswer = $formattedAnswer.$result;
}
return nl2br($formattedAnswer);
}
function operate($text,$ops,$attribute){
$operatedText = null;
switch($ops){
case 'bold':
$operatedText = '<strong>'.$text.'</strong>';
break;
case 'italic':
$operatedText = '<i>'.$text.'</i>';
break;
case 'strike':
$operatedText = '<s>'.$text.'</s>';
break;
case 'underline':
$operatedText = '<u>'.$text.'</u>';
break;
case 'link':
$operatedText = ''.$text.'';
break;
default:
$operatedText = $text;
}
return $operatedText;
}
Here's a full function using quill.root.innerHTML, as the others didn't quite cover the complete usage of it:
function quillGetHTML(inputDelta) {
var tempQuill=new Quill(document.createElement("div"));
tempQuill.setContents(inputDelta);
return tempQuill.root.innerHTML;
}
This is just a slight different variation of km6 's answer.
For Quill version 1.3.6, just use:
quill.root.innerHTML;
Try it online: https://jsfiddle.net/Imabot/86dtuhap/
Detailed explaination on my blog
This link if you have to post the Quill HTML content in a form
quill.root.innerHTML on the quill object works perfectly.
$scope.setTerm = function (form) {
var contents = JSON.stringify(quill.root.innerHTML)
$("#note").val(contents)
$scope.main.submitFrm(form)
}
I put together a node package to convert html or plain text to and from a Quill Delta.
My team used it to update our data model to include both Quill's Delta and HTML. This allows us to render on the client without an instance of Quill.
See node-quill-converter.
It features the following functions:
- convertTextToDelta
- convertHtmlToDelta
- convertDeltaToHtml
Behind the scenes it uses an instance of JSDOM. This may make it best suited for migration scripts as performance has not been tested in a typical app request lifecycle.
Try
console.log ( $('.ql-editor').html() );
Here is how I did it, for you Express folks. It seems to have worked very well in conjunction with express-sanitizer.
app.js
import expressSanitizer from 'express-sanitizer'
app.use(expressSanitizer())
app.post('/route', async (req, res) => {
const title = req.body.article.title
const content = req.sanitize(req.body.article.content)
// Do stuff with content
})
new.ejs
<head>
<link href="https://cdn.quilljs.com/1.3.2/quill.snow.css" rel="stylesheet">
</head>
...
<form action="/route" method="POST">
<input type="text" name="article[title]" placeholder="Enter Title">
<div id="editor"></div>
<input type="submit" onclick="return quillContents()" />
</form>
...
<script src="https://cdn.quilljs.com/1.3.2/quill.js"></script>
<script>
const quill = new Quill('#editor', {
theme: 'snow'
})
const quillContents = () => {
const form = document.forms[0]
const editor = document.createElement('input')
editor.type = 'hidden'
editor.name = 'article[content]'
editor.value = document.querySelector('.ql-editor').innerHTML
form.appendChild(editor)
return form.submit()
}
</script>
express-sanitizer (https://www.npmjs.com/package/express-sanitizer)
document.forms (https://developer.mozilla.org/en-US/docs/Web/API/Document/forms)
My view only has one form, so I used document.forms[0], but if you have multiple or may extend your view in the future to have multiple forms, check out the MDN reference.
What we are doing here is creating a hidden form input that we assign the contents of the Quill Div, and then we bootleg the form submit and pass it through our function to finish it off.
Now, to test it, make a post with <script>alert()</script> in it, and you won't have to worry about injection exploits.
That's all there is to it.
Here is a proper way to do it.
var QuillDeltaToHtmlConverter = require('quill-delta-to-html').QuillDeltaToHtmlConverter;
// TypeScript / ES6:
// import { QuillDeltaToHtmlConverter } from 'quill-delta-to-html';
var deltaOps = [
{insert: "Hello\n"},
{insert: "This is colorful", attributes: {color: '#f00'}}
];
var cfg = {};
var converter = new QuillDeltaToHtmlConverter(deltaOps, cfg);
var html = converter.convert();
Refer https://github.com/nozer/quill-delta-to-html
For a jQuery-style solution that allows getting and setting the Quill value I am doing the following:
Quill.prototype.val = function(newVal) {
if (newVal) {
this.container.querySelector('.ql-editor').innerHTML = newVal;
} else {
return this.container.querySelector('.ql-editor').innerHTML;
}
};
let editor = new Quill( ... );
//set the value
editor.val('<h3>My new editor value</h3>');
//get the value
let theValue = editor.val();
quill-render looks like it's what you want. From the docs:
var render = require('quill-render');
render([
{
"attributes": {
"bold": true
},
"insert": "Hi mom"
}
]);
// => '<b>Hi mom</b>'
If you want to render quill using nodejs, there is a package quite simple based on jsdom, usefull to render backside (only one file & last update 18 days from now) render quill delta to html string on server
Just use this clean library to convert from delta from/to text/html
node-quill-converter
example:
const { convertDeltaToHtml } = require('node-quill-converter');
let html = convertDeltaToHtml(delta);
console.log(html) ; // '<p>hello, <strong>world</strong></p>'

Polymer: Step through array on button click

I am trying to update the URL bar on a button press, and cycle through JSON objects that are declared in the tag array.
The iterator works fine when the window.location.href = "http://localhost:777/tag/" + this.tag[this.counter]; line is commented out, but gets stuck on the first array item when this line is active.
I think counter gets reset when the page is refreshed. Is there a good way to save the state of the counter so I can cycle through the array as the URL changes?
<template>
<paper-button class="menu-button" on-tap="leftArrowButton">Button Text</paper-button>
</template>
<script>
Polymer({
is: 'sub-menu',
properties: {
tag: {
type: Array,
value: function () {
return ['one', 'two', 'three', 'four'];
}
},
counter: {
type: Number,
value: 0
}
},
leftArrowButton: function (e) {
this.counter = (this.counter + 1) % this.tag.length;
console.log(this.counter);
console.log(this.tag.length);
console.log(this.tag[this.counter]);
console.log("http://localhost:777/tag/" + this.tag[this.counter])
window.location.href = "http://localhost:777/tag/" + this.tag[this.counter];
}
});
</script>
You need a router to manage your app's state between pages. Check out app-route. It was built by the Polymer team as a "web components" approach to routing.
Using your links will reload the page and reset the counter. You might either want to use hashbang in your URLs like http://localhost:777/tag#one or query params like http://localhost:777/tag?choice=one. Prior will prevent a page load, latter won't but lets you parse the link (see below).
If altering the link structure is no option you could read the currently selected option from location.pathname in leftArrowButton, calculate the index of the corresponding tag entry, choose the next and build your link with that:
leftArrowButton: function (e) {
var current = location.href.substr(location.href.lastIndexOf('/') + 1);
var index = this.tag.indexOf(current);
var counter = (index + 1) % tags.length;
...

Resources