CKEditor 5 Insert text on button click - Pure JS - javascript

I'm trying to create a sort of dropdown menu that a user can insert tokens into a CKEditor with. I've found that I can insert text in an editor with this code:
editorInstance.model.change( writer => {
let pos = editorInstance.model.document.selection.getFirstPosition();
writer.insertText( "TEST", pos,0);
});
It works when I put it in the ClassicEditor.create.then for testing but it does nothing when I place this in a $().click event. I can log something from inside the callback so I know the code is executed but nothing is inserted.
I've been trying to get this working for hours now but all the examples I can find is in angular or any other frameworks.

I Solved the issue you faced as follows
first defined new editor that is null and Then instatiate Ckeditor 5
let neditor = null;
ClassicEditor.create(document.querySelector('#editor'))
.then(editor => {
neditor = editor;
})
.catch(error => {
console.error(error);
});
using pure js
document.addEventListener("click", (event) => {
var button = event.target;
if (event.target.type === 'button' && event.target.className.includes('testtokenbutton')) {
neditor.model.change(writer => {
const insertPosition = neditor.model.document.selection.getFirstPosition();
writer.insertText(button.id, insertPosition);
});
}
});

Related

Why doesn't my class names update when set though JS?

This may be a really simple problem but I can't seem to find why this is happening. I'm trying to develop a SPA in vanilla js using webpack, so far I was able to implement routing
with hashchange event and triggering rerendering. But when I tried to add an active class to the relevant link though when the hash changes, It doesn't work. But when I log to the console, it seems that class was added successfully, but in the HTML it doesn't get updated. Why is this?
this is my hashchange listener,
window.addEventListener("hashchange", (e) => {
const hash = window.location.hash.replace("#", "");
const view = routes.find((route) => {
return route.path == hash;
});
const links = document.querySelectorAll(".nav-list--link");
app.render(view.name);
links.forEach((l) => {
const hashHref = l.getAttribute("href").replace("/#", "");
if (hash === hashHref) {
l.classList.add("active");
console.log(l, l.classList);
} else {
l.classList.remove("active");
console.log(l, l.classList);
}
});
});
And this is the console output,
This is the HTML,
I don't understand why it doesn't update in the HTML if it's shown as updated in Javascript

JS DOM issue: Uncaught TypeError: Cannot read property 'addEventListener' of null becomes Uncaught Reference Error

This is code that i've downloaded from a tutorial here: (https://codepen.io/Web_Cifar/pen/PoNNEYY) in hopes of adapting it to something that i am working on. I've pieced it together and while it works in the demo (and there's a nice YT video where he goes thru it), it doesn't work for me in a live situation. I am attempting to build a Gravity Forms-like multi-page data entry form (GF has some quirks that don't work for me).
The first Javascript error that i got was: "Uncaught TypeError: Cannot read property 'addEventListener' of null". Researching that here on StackO, i got the idea that the general advice is that perhaps the DOM is not loaded for my document yet and we are calling JS before that has taken place, and two suggestions seem popular:
1). Move your JS file to the bottom of your HTML document, just before the close of your body tag (it WAS originally in my tag... moving it changed nothing).
2. Wrap your JS function in question in the following code: "window.addEventListener('DOMContentLoaded', (event) => {"
to force the DOM to load before calling the function.
Doing #2 changed the error to: ReferenceError: "changeStep" is not defined. There IS a function called 'changeStep' in the JS code. If you reference the tutorial above, you'll see that it was originally the last function defined in the JS file, so i thought that moving it to the top would change it. No dice. I've done some checks to see if some simple JQuery tests work in my environment and they do. I am relatively new to JS but i don't see why the DOM would not be loaded nor do i see why the function in question cannot be referenced.
Here is a skeleton of my HTML code:
<html>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script> /* A recommended test to see if jQuery is working, and it is. */
$(document).ready(function(){
$("button").click(function(){
alert("jQuery is working perfectly.");
});
});
</script>
<link rel="stylesheet" href="/Users/Me/Documents/multistep.css">
<body>
etc.....(moving to end of html file....)
<script type = "text/javascript" src = "/Users/Me/Documents/multistep.js" ></script>
</body>
</html>
And here is my entire JS script:
const steps = Array.from(document.querySelectorAll("form .step"));
const nextBtn = document.querySelectorAll("form .next-btn");
const prevBtn = document.querySelectorAll("form .previous-btn");
const form = document.querySelector("form");
window.addEventListener('DOMContentLoaded', (event) => {
function changeStep(btn) {
let index = 0;
const active = document.querySelector(".active");
index = steps.indexOf(active);
steps[index].classList.remove("active");
if (btn === "next") {
index++;
} else if (btn === "prev") {
index--;
}
steps[index].classList.add("active");
}
});
window.addEventListener('DOMContentLoaded', (event) => {
nextBtn.forEach((button) => {
button.addEventListener("click", () => {
changeStep("next");
});
});
});
window.addEventListener('DOMContentLoaded', (event) => {
prevBtn.forEach((button) => {
button.addEventListener("click", () => {
changeStep("prev");
});
});
});
window.addEventListener('DOMContentLoaded', (event) => {
form.addEventListener("submit", (e) => {
e.preventDefault();
const inputs = [];
form.querySelectorAll("input").forEach((input) => {
const { name, value } = input;
inputs.push({ name, value });
});
console.log(inputs);
form.reset();
});
});
Please note that i wrapped basically everything in the "window.addEventListener..." tag (as per advice Googled above) and the only other change i made from the referenced demo (that works in codePen) was to move the changeStep function to the first function in the file.
I'm at a loss as to what is going on. Can an experienced JS guy help me get un-stuck here?
changeStep is defined inside the anonymous callback function of the first event listener, so it is only visible inside that function. If you want to access it outside that function's scope, you have to define it outside of the function, i.e. before calling addEventListener. But a better solution is to put everything in one event listener. I do not see a reason why there have to be three of them.
Besides, since you are still calling querySelector outside the event listener, it does not solve the original problem. That is exactly the thing you want to do after the DOM context has been loaded, so you have to put it inside the event listener, too.
So the solution is to put basically everything in one event listener:
window.addEventListener('DOMContentLoaded', (event) => {
const steps = Array.from(document.querySelectorAll("form .step"));
const nextBtn = document.querySelectorAll("form .next-btn");
const prevBtn = document.querySelectorAll("form .previous-btn");
const form = document.querySelector("form");
function changeStep(btn) {
let index = 0;
const active = document.querySelector(".active");
index = steps.indexOf(active);
steps[index].classList.remove("active");
if (btn === "next") {
index++;
} else if (btn === "prev") {
index--;
}
steps[index].classList.add("active");
}
nextBtn.forEach((button) => {
button.addEventListener("click", () => {
changeStep("next");
});
});
prevBtn.forEach((button) => {
button.addEventListener("click", () => {
changeStep("prev");
});
});
});
This should answer your question about why you get the second error, but actually putting the script at the end of the body tag should have solved the problem in the first place, so the first error probably has a different reason. Are you sure that your script tag was at the very end of the body tag, and that you actually have all the elements you are querying in your DOM tree?

HTML Component That Is Fetched With JavaScript Not Responding To Click Event

I have an HTML component that is fetched when user clicks on a button. This component/modal is used to change a user's profile image (this is processed with PHP). The JavaScript fetch() happens with the following code:
var newProfileImageButton = document.getElementById('replace-profile-photo'),
changeProfileImageWrapper = document.getElementById('change-profile-image-wrapper'),
profileImageModalPath = "modals/change-profile-image.php";
newProfileImageButton.addEventListener('click', function(){
fetch(profileImageModalPath)
.then((response) => {
return response.text();
})
.then((component)=>{
changeProfileImageWrapper.innerHTML = component;
})
.catch((error => {console.log(error)}))
})
This fetched component includes a 'close' button should the user wish to close the modal and not update their profile image.
When I click the close button though nothing is happening. I have the script below - is the issue to do with the fact the Javascript has loaded before the component/modal is fetched? And if so how do I fix this? I guess I could just toggle display:none off and on for this component but would prefer to fetch it if possible.
Note: The button is responding to CSS hover events so I'm confident it's not an HTML / CSS markup issue.
// close button is part of the HTML component that is fetched
var closeComponent = document.getElementById('form-close-x')
if (closeComponent) {
closeComponent.addEventListener('click', function(){
// Hide the main component wrapper so component disappears
changeProfileImageWrapper.style.display = 'none';
})
}
I've also tried using the following code, which I found in a similar question, but this doesn't work either (it was suggested this was a duplicate question).
var closeComponent = document.getElementById('form-close-x')
if (closeComponent) {
closeComponent.addEventListener('click', function(e){
if (e.target.id == 'form-close-x') {
changeProfileImageWrapper.style.display = 'none';
}
})
}
Try this:
// var closeComponent = document.getElementById('form-close-x') <-- remove
// if (closeComponent) { <-- remove
document.addEventListener('click', function(e){
if (e.target.id === 'form-close-x') {
changeProfileImageWrapper.style.display = 'none';
}
})
//} <-- remove

React App.tsx Expression Expected in script tag

So I am having this issue where I am building a React App using typescript. I am using Bulma, the css library and I copy and pasted vanilla javascript. However, I keep getting an error here:
<script>
const $navbarBurgers``` where it is a ts1109 error saying expression expected. Also, even if I add a type to it, the error still persists. What is going on?
```<script>
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Check if there are any navbar burgers
if ($navbarBurgers.length > 0) {
// Add a click event on each of them
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
}
});
</script>

javascript console log shows couple values

I am learning Javascript. I am creating simple budget application and I have a problem. I will pass only necessary code, to help me. So constructor is bigger, but I pass only necessary things:
class BudgetApp {
constructor() {
this.expenseListForm = document.querySelector("#expense-list");
}
deleteItemFromExpensesList(event) {
Array.from(event.currentTarget.querySelectorAll(".delete-icon")).forEach((element) => {
element.addEventListener("click", (e) => {
console.log(e.currentTarget);
})
})
}
}
eventListeners = () => {
const budgetApp = new BudgetApp();
budgetApp.expenseListForm.addEventListener("click", (event) => {
event.preventDefault();
budgetApp.deleteItemFromExpensesList(event);
})
}
document.addEventListener('DOMContentLoaded', () => {
eventListeners();
});
When I click ".delete-icon" which is <a> tag my console.log show nothing, when I click second time then console.log shows exactly what I want, when I click third time console_log shows this <a> tag two times and so on. I want to get result when I click one time, console_log shows me my <a> tag exactly once.
What should I improve in my code? Thanks Guys.

Categories