Multirow selection(getRangeAt) and surroundContents() for text editor - javascript

Im trying to create a simple text editor for a web site.
I want to add to him something like the code button in this site.
So by selecting a specific text, color it's background with gray color.
Here is what i have for now but if i have a multi row text selected(rows created by pressing enter) the function test() doesn't work. It works only if i select a row each time.
<!DOCTYPE html>
<html lang="en" xmlns="http://www.w3.org/1999/html">
<head>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<link rel="stylesheet" href="Awesome/css/font-awesome.css">
</head>
<body onload="InitEditable()">
<div style="margin-left:10px;">
<p>
<div class="btn-group">
<a class="btn" href="#" onclick="fontEdit('bold')"><i class="icon-bold"></i></a>
<a class="btn" href="#" onclick="fontEdit('italic')"><i class="icon-italic"></i></a>
<a class="btn" href="#" onclick="fontEdit('underline')"><i class="icon-underline"></i></a>
<a class="btn" href="#" onclick="test()"><i class="icon-link"></i></a>
<a class="btn" href="#" onclick="fontEdit('justifyLeft')"><i class="icon-align-left"></i></a>
<a class="btn" href="#" onclick="fontEdit('justifyCenter')"><i class="icon-align-center"></i></a>
<a class="btn" href="#" onclick="fontEdit('justifyRight')"><i class="icon-align-right"></i></a>
<a class="btn" href="#" onclick="fontEdit('justifyFull')"><i class="icon-align-justify"></i></a>
</div>
</p>
</div>
<div style="margin-left:10px;"><iframe id="textEditor" style="width:500px;height:170px;font-family:arial;font-size:11px;"></iframe></div>
<script type="text/javascript">
var editorDoc;
var editor;
function InitEditable()
{
editor = document.getElementById("textEditor");
editorDoc = editor.contentwindow.document;
var editorBody = editorDoc.body;
if ('contentEditable' in editorBody) {
// allow contentEditable
editorBody.contentEditable = true;
}else { // Firefox earlier than version 3
if ('designMode' in editorDoc) {
// turn on designMode
editorDoc.designMode = "on";
}
}
}
function fontEdit(x,y)
{
editorDoc.execCommand(x,"",y);
editorDoc.focus();
}
function test(){
var range = document.getElementById("textEditor").contentwindow.window.getSelection().getRangeAt(0);
var newNode = document.createElement('div');
newNode.style.backgroundColor = "gray";
range.surroundContents(newNode);
return false;
}
</script>
</body>
</html>
There must be a problem with surroundContents() and divs but cannot think something to solve it.
Any idea is welcomed!
Thanks in advance.

One option is the class applier module of my Rangy library (demo)
Live demo: http://jsfiddle.net/D7s5j/
CSS:
.code {
background-color: #ccc;
font-family: Courier New, monospace;
}
JS:
var codeApplier = rangy.createCssClassApplier("code");
codeApplier.applyToSelection();

So the problem is that the contenteditable object, creates <div> so this couldn't let surroundContents() work properly and add it's own <div>s around the selected range.
I solve my problem finally by adding this code
$("#textEditor>div").replaceWith(function() { return $(this).contents(); });
which deletes <div>s tags from the contenteditable object.
Also you can add this for create a <br> tag after enter pressed.
$("#textEditor > div").before("<br />").contents().unwrap();
For the second code thank VisioN.

Related

Does anyone know how to create a menu without exiting the page?

Does anyone know how to create a menu without exiting the page? I want to create a settings menu.
<style>
.material-symbols-outlined {
align: right;
font-variation-settings:
'FILL' 0,
'wght' 400,
'GRAD' 0,
'opsz' 48
}
</style>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD#20..48,100..700,0..1,-50..200" />
<a OnClick="open()" <span class="material-symbols-outlined">
engineering
</span></a>
<div class="menu">
<p>Settings</p>
</div>
(I know that i should not use onclick but i don't know how to use anything else)
<script>
function show(){
div.menu.show=(true)
}
</script>
I wanted it to show div but div is always shown
Welcome!
you want to use style="display:none" on your div
and in the show() function, you want to try this :
document.getElementsByClassName('menu')[0].style.display = "block";
The issue why your <div> is always showing is that you never used any CSS to hide it, and the reason why your onClick handler isn't working is because you are calling a function that hasn't been defined.
You can add an event listener to the link and toggle the .style.display attribute of the menu.
document.getElementById('openMenu').addEventListener('click', () => {
const menu = document.getElementById('menu');
if (menu.style.display === 'block') menu.style.display = 'none';
else menu.style.display = 'block';
});
#menu {
display: none;
}
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,GRAD#20..48,100..700,0..1,-50..200" />
<a id="openMenu">
<span class="material-symbols-outlined">engineering</span>
</a>
<div id="menu">
<p>Settings</p>
</div>

How to remove text between <a> with javascript

I am using javascript and jquery to change the text inside of an a tag. I was reading that document.getElementById("yearA").innerHTML = ''; would remove the text but it isn't working. I'm not sure if it's because I am adding text to the a tag then trying to remove it or not. Any help with this would be appreciated. Here is my html
document.getElementById("filter-div").style.visibility = "visible";
document.getElementById("yearA").style.visibility = "visible";
document.getElementById("yearA").innerHTML += 'Remove Link';
console.log('Link added')
function hideYear() {
document.getElementById("yearA").innerHTML = '';
console.log('Link removed')
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="hidden" id="hiddenTag" />
<div id="filter-div" class="filter-div" style="visibility: hidden;">
<a id="yearA" onclick="hideYear()" style="visibility: hidden;"></a>
</div>
Jquery based solution
you may try:
$('#yearA').text("");
I'm not sure why you are throwing jquery into the mix, but here is a full example with hide and show functions
HTML:
<input type="hidden" id="hiddenTag" />
<div id="filter-div" class="filter-div" style="visibility: hidden;">
<a id="yearA" onclick="hideYear(event)"></a>
<div id="showYear" onclick="showYear(event)" style="visibility: hidden;">
show year
</div>
</div>
Javascript:
const year = new Date().getYear();
document.getElementById("filter-div").style.visibility = "visible";
document.getElementById("yearA").innerHTML += "Remove " + year;
function hideYear(evt) {
evt.preventDefault();
evt.stopPropagation();
document.getElementById("showYear").style.visibility = "visible";
document.getElementById("yearA").innerHTML = "";
}
function showYear(evt) {
evt.preventDefault();
evt.stopPropagation();
document.getElementById("showYear").style.visibility = "hidden";
document.getElementById("yearA").innerHTML = "Remove " + year;
}
Maybe you're looking for something like this? Let me know.
function hideYear() {
document.getElementById("yearA").innerHTML = '';
}
<input type="hidden" id="hiddenTag" />
<div id="filter-div" class="filter-div">
<a id="yearA" onclick="hideYear()">test</a>
</div>
Don't make use of innerHTML. That will change the entire html node. If your requirement is just to clear the text within the element, try making use if innerText property. Select the node either via JavaScript or jQuery, update the innerText, that will preserve the href of the anchor tag.
Try making use of innerText.
JavaScript Implementation
function removeText() {
document.getElementById('google').innerText = '';
}
Go To Google
<button onclick="removeText()">Remove Text</button>
jQuery Implementation
function removeText() {
$('#google').text('');
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
Go To Google
<button onclick="removeText()">Remove Text</button>

Opening and closing pictures with single buttons (JavaScript)

I am new to JavaScript. I created this code in order to try and make buttons that will hide
and show certain pictures on the page. I have 3 buttons, the first of which is supposed to run my JavaScript code in <script></script> tags, the other two just have Javascript code inside them and they work fine. But they don't hide the picture once they are clicked a second time, which is why I am trying to do that for the first one if possible.
For some reason, I cannot get the first button with "open()" to work the way I want with my Javascript code. Can anyone with more experience please explain to me what I am doing wrong? Thank you in advance...
var btn1 = document.getElementById('1');
var btn2 = document.getElementById('2');
var btn3 = document.getElementById('3');
var display1 = btn1.getAttribute('display')
var display2 = btn2.getAttribute('display')
var display3 = btn3.getAttribute('display')
function open() {
if (display1 === ('none')) {
btn1.setAttribute('display', 'block');
} else {
btn1.setAttribute('display', 'none');
}
}
<img id="1" src="forge.PNG" style="height:320px; display:none; padding:10px">
<img id="2" src="lizard.jpg" style="height:320px; display:none; padding:10px">
<img id="3" src="walkway.jpg" style="height:320px; display:none; padding:10px">
<button onclick="open()">1</button>
<button onclick="document.getElementById('2').style.display='block'">2</button>
<button onclick="document.getElementById('3').style.display='block'">3</button>
I'd use event delegation to watch for clicks on the container. When the nth button is clicked, select the nth image, and toggle a class that hides/shows the image:
const images = document.querySelectorAll('img');
const buttons = [...document.querySelectorAll('button')];
document.addEventListener('click', (e) => {
if (e.target.matches('button')) {
const i = buttons.indexOf(e.target);
images[i].classList.toggle('hidden');
}
});
.hidden {
display: none;
}
<img id="1" src="https://www.gravatar.com/avatar/34932d3e923ffad9a4a1423e30b1d9fc?s=48&d=identicon&r=PG&f=1" style="height:320px; padding:10px" class="hidden">
<img id="2" src="https://www.gravatar.com/avatar/978ec0c47934c4b04401a8f4b4fec8bd?s=32&d=identicon&r=PG&f=1" style="height:320px; padding:10px" class="hidden">
<img id="3" src="https://lh3.googleusercontent.com/-uIr21N5ccCk/AAAAAAAAAAI/AAAAAAAAHeg/ohNEkpJKXQA/photo.jpg?sz=32" style="height:320px; padding:10px" class="hidden">
<button>1</button>
<button>2</button>
<button>3</button>
Problems with your original code include:
You're trying to select the elements before they exist in the DOM
Elements do not have a display property - in order to check the style of an element, you have to access its .style property first (eg, someImage.style.display)
Similarly, to set the style of an element, you have to set a property of its style property (eg someImage.style.display = <newDisplay>). Setting the display attribute of the element won't do anything.
Try to avoid inline handlers if at all possible - they have many problems and are pretty much universally considered to be quite poor practice. Always attach listeners properly using Javascript instead, whenever that's an option.
The event listener is the better solution, but if you want to see a working code in your way:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>switchpics</title>
</head>
<script type="text/javascript">
var open = function(param) {
img = document.getElementById(param.innerHTML);
if (img.style.display == 'none'){
img.style.display = "block";
} else {
img.style.display = "none";
};
};
</script>
<body>
<img id="1" src="1.jpg" style="height:20px; display:block; padding:10px">
<img id="2" src="1.jpg" style="height:20px; display:none; padding:10px">
<img id="3" src="1.jpg" style="height:20px; display:none; padding:10px">
<button onclick="open(this)">1</button>
<button onclick="open(this)">2</button>
<button onclick="open(this)">3</button>
</body>
</html>

Trying to change a link on button click with javascript

I have three buttons and i want such tha when i click on one button the link on an a tag changes
<a class="payverlink" href="exbronzeregistrationform.php">Continue to registration</a>
<button class="goldpac">Choose Plan</button>
<button class="silverpac">Choose Plan</button>
<button class="bronzepac">Choose Plan</button>
I want such that when i click on one button, it changes the link at .payverlink
I have tried
function bronze()
{
$('.payverlink').href="exbronzeregistrationform.php";
}
function silver()
{
$('.payverlink').href="exsilverregistrationform.php";
}
<button class="silverpac" onclick="silver()">Choose Plan</button>
<button class="bronzepac" onclick="bronze()">Choose Plan</button>
But this changes to bronze function onclick of any of the buttons. Please whats the issue.
You could set your javascript code to trigger the button click and avoid using the onclick into html
$(document).ready(function() {
$("button").on('click', function(){
if ($(this).hasClass('goldpac')) {
window.location="http://..."; /* or exbronzeregistrationform.php for example */
} else if ($(this).hasClass('silverpac')) {
window.location="http://..."; /* or exbronzeregistrationform.php for example */
} else if ($(this).hasClass('bronzepac')) {
window.location="http://..."; /* or exbronzeregistrationform.php for example */
}
});
});
You could add one more line in each case changing the a tag, but ti wont make a huge difference in your actions as it isn't used as you click the buttons.
$("a.payverlink").attr("href", "http://...."); /* or exbronzeregistrationform.php for example */
So, you could just remove the 'href' as you contantly will change the url from js.
Use attr or prop, attr stands for attribute and prop for property!
$(
function(){
$('#google').attr('href', 'https://duckduckgo.com/');
//or use prop
$('#duckduckgo').prop('href', 'https://bing.com')
}
);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>JS Learning</title>
</head>
<body>
<h1 class="header"></h1>
<a id="google" href="https://google.com/">google is down!</a>
<br>
<a id="duckduckgo" href="https://duckduckgo.com/">I'm slow...</a>
</body>
</html>
I suspect that both functions are failing, since there is no such property href on JQuery object.
Use this approach instead:
$('.payverlink').prop("href","exbronzeregistrationform.php");
Have you try .prop() method of jQuery hopefully it works .
function bronze()
{
$('.payverlink').prop('href','exbronzeregistrationform.php');
}
function silver()
{
$('.payverlink').prop('href','exsilverregistrationform.php');
}
You can use the .attr function:
function bronze(){
changeLink('exbronzeregistrationform');
}
function silver(){
changeLink('exsilverregistrationform.php');
}
function changeLink(url){
$('.payverlink').attr('href',url);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a class="payverlink" href="exbronzeregistrationform.php">Continue to registration</a>
<button class="silverpac" onclick="silver()">Choose Plan silverpac</button>
<button class="bronzepac" onclick="bronze()">Choose Plan bronzepac</button>
function bronze()
{
$('.payverlink').attr("href","exbronzeregistrationform.php");
}
function silver()
{
$('.payverlink').attr("href","exsilverregistrationform.php");
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<a class="payverlink" href="exbronzeregistrationform.php">Continue to registration</a>
<button class="goldpac">Choose Plan</button>
<button class="silverpac" onclick="silver()">Choose Plan</button>
<button class="bronzepac" onclick="bronze()">Choose Plan</button>
You can try this. it will helps you. :)

html multiselect images

I printed to the screen 16 icons (little pictures).
Now I want to be able to select icons,
and when I press a button the selected icons ids will be sent in a form.
I saw in the net only checkboxes and lists multiselect,
what's the best way to do this?
(I'm pretty new to web design)
thanks ahead!
Although jQuery isn't in your tags, you should introduce yourself to jQuery. It'll make your life easier, for what you're trying to do. Here is the basic steps both if you use jQuery and if use just Javascript:
With jQuery
Give all your icons a class and each one a unique id:
<img src='icon1.png' data-iconID=2233 class='myIcons' />).
Then bind that class to a click event
$('.myIcons').bind('click', function() {
$(this).toggleClass('selectIcon');
});
Attach form submit function to onsubmit:
<form ... onsubmit="submitForm();">
Build submitForm function:
function submitForm() {
var csvIconIds = '';
$.each($('.myIcons.selectIcon'), function (index, value) {
csvIconIds += $(value).attr('data-iconID');
});
//submit scvIconIds here along with other form data (ajax?)
}
With Javascript
Similar as above but way more complicated...
To toggle classes see this thread: How to add/remove a class in JavaScript?
To getting attributes by class see this site: http://www.actiononline.biz/web/code/how-to-getelementsbyclass-in-javascript-the-code/
This could be a way using just plain Javascript or jQuery. I prefer the jQuery version, since it separates the click handler from the markup, instead of using inline onclick handlers, which are in general discouraged.
What this does is use an input element array, which you can create by adding [] to the element name. This same technique can be used on SELECTs and other elements, since it signals to the server that an array has been submitted, as opposed to value known by a single key.
<html>
<head>
<style type="text/css">
div img {
cursor: pointer;
border: 1px solid #f00;
}
</style>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.js"></script>
<script>
function setFormImage(id) {
if (id != '' && !document.getElementById('input_'+id)) {
var img = document.createElement('input');
img.type = 'text';
img.id = 'input_'+id;
img.name = 'images[]';
img.value = id;
document.imageSubmit.appendChild(img);
}
}
$(document).ready(function(){
$('#jqueryimages img').click(function(){
setFormImage(this.id);
});
});
</script>
</head>
<body>
<pre><?php
if (count($_GET['images'])) {
print_r($_GET['images']);
}
?></pre>
<div style="float: left; width: 49%;">
<h1>Plain ol' HTML</h1>
1. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="img-1" onclick="setFormImage(this.id)"/>
<br/>
2. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="img-2" onclick="setFormImage(this.id)"/>
<br/>
3. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="img-3" onclick="setFormImage(this.id)"/>
<br/>
4. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="img-4" onclick="setFormImage(this.id)"/>
</div>
<div id="jqueryimages" style="float: left; width: 49%;">
<h1>jQuery</h1>
5. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="img-5"/>
<br/>
6. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="img-6"/>
<br/>
7. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="img-7"/>
<br/>
8. <img src="http://www.gravatar.com/avatar/e1122386990776c6c39a08e9f5fe5648?s=128&d=identicon&r=PG" id="img-8"/>
</div>
<h1>Form Submit</h1>
<form name="imageSubmit" method="get">
<input type="submit" value="View Selected"/>
</form>
</body>
</html>
try this
var idArray = [];
$("#container-id img").each(function(index,value){
idArray.push($(value).attr("id"));
});
//do anything with the array

Categories