I am working on WYSIWYG editor which have button IncreaseFontSize (like in MS Office). I am trying to make this button works but without success. Everytime all selected elements have the same font size. Here is example:
<div contenteditable="true">
<p>
Some
<span style="font-size: 20pt">Text</span>
<span style="font-size: 32pt">Some</span>
Text
</p>
</div>
Below is part of my code
var html = $(rangy.getSelection().toHtml());
var firstValue = html.find('.fontSize').first().css('font-size').replace('px', '');
html.find('.fontSize').each(function () {
$(this).css('font-size', parseInt(firstValue) + 1);
});
When I select all text and click this button all spans have the same font-size (for example 21pt, because my function brings only first span into consideration). So how can I do script which can increase font size of each element separately (using JavaScript or/and JQuery)? Thanks for help.
You are grabbing the value of the first span, storing it in firstValue and then setting the font size of ALL the spans to firstValue + 1. Since your first span is 20px, everything gets set to 21px
So if you are trying to increase each span by 1px when the button is clicked, you would do it this way:
html.find('.fontSize').each(function () {
var oldValue = $(this).css('font-size');
$(this).css('font-size', parseInt(oldValue) + 1);
});
Related
I am trying to make a content editable div that can be used to generate message templates for an app. Users can append placeholders for fields like names to a template by hitting a button. The placeholders can be removed by hitting an 'x' on them as well. Here's the working snippet.
var removePlaceholder = function(e){
e.parentNode.parentNode.removeChild(e.parentNode);
}
var appendPlaceHolder = function(field){
var e = document.getElementById("t");
e.innerHTML += ('<span class="tag">{'+field+'}<span onclick=removePlaceholder(this) class="remove">x</span></span>')
}
.tag {
background-color : blue;
color : white;
}
.remove {
color : red
}
<div id="t" contenteditable="true">Hello</div>
<button onclick=appendPlaceHolder("first_name")>Add first name</button>
The contenteditable part works just fine. But after I've added a placeholder using my appendPlaceHolder function, everything I type seem to get appended to the last inserted HTML element.
How can I prevent this. I have closed the tag properly. Is there any way to change this behaviour.
To recreate issue, run the snippet and hit the "Add First Name" Button, then continue typing in the area.
Update
Have added image to explain the situation
What you can do is add a space after the placeholder has been appended:
JavaScript
var removePlaceholder = function(e){
e.parentNode.parentNode.removeChild(e.parentNode);
}
var appendPlaceHolder = function(field){
var e = document.getElementById("t");
e.innerHTML += ('<span class="tag">{'+field+'}<span onclick=removePlaceholder(this) class="remove">x</span></span> ')
}
Note: The which has been added at the end of the span just creates a space.
Live Example
JSFiddle
I want to programmatically add words in input and always see the end of the text. But the problem is that when I'm adding word (like input.value += 'word') when length of text is almost the same as length of input, text inside input doesn't move, so I can see only begining of the text and ending is become hidden.
I think if I could put cursor to the end of input it will help, but none of tricks with cursor not working in Chrome, such as
input.value = input.value
or
input.setSelectionRange(input.value.length, input.value.length);
Seems to work well enough:
let input = document.getElementById('auto');
let sentence = 'Courage is the magic that turns dreams into reality.';
let index = 0;
setTimeout(function typing() {
let letter = sentence.charAt(index++);
input.blur();
input.value += letter;
input.focus();
input.setSelectionRange(index, index);
if (index < sentence.length) {
let ms = Math.floor(75 + Math.random() * 150);
setTimeout(typing, ms);
}
}, 1000);
<input id="auto" type="text">
If the input does not have focus, then Chrome will show it "scrolled" all the way to the left, showing the beginning of your input value.
If the element has focus, then you can set the selection range to move the cursor:
window.onload = function(){
var input = document.getElementById('foobar');
input.value += ' bazbat';
input.focus();
input.setSelectionRange( input.value.length - 1 );
}
<input id="foobar" value="foobar" size="6">
But it would be a very confusing and frustrating UX if the cursor is moving around while the user is attempting to type a value.
Other options to consider:
Change the width of your input to match the value. make html text input field grow as I type?
Toggle between an input and a span (edit mode vs read mode). With a span, you'd have a lot more control over how text is displayed. Jquery: Toggle between input and text on click
Use an indicator of some sort to alert the user that one of their input values was modified. This would be useful even if they can see the entire value, as they might not notice that the value was updated.
I have a <div> with a fixed height and overflow-y: scroll. Inside this div, I have primarily a <p> tag containg a long text with some highlithing (spans with background-color and a numbered id attribute).
By the way, it is a HTMl5 application with AngularJS.
Now I like to implement a button to jump through the highlighted positions: I like to get the div scrolled to the right position and the rest of the page shall stay untouched i.e. "unscrolled".
How can I achieve that the div is scrolled to the right position and not the whole page is scrolled down disturbing the page layout?
On principle, I know that I can use hashtag + id in the url to go to the element with a given id - I also found $anchorScroll from AngularJS but it seems not to be the right way, since it scrolles down the whole browser content instead of just inside my scrollable div.
Years ago, as using an iframe was not ugly, it was easy to use an iframe for this; however, today, I think there must be better solutions.
Any help is appreciated!
Thanks in advance.
Here's an example that might help you. It uses jQuery to set the scrollTop on a target <div> without scrolling the rest of the document.
To use it, enter a number between 0-99 in the <input> field and click Submit. The div should scroll to the top of the <span> element (within the target div) with that numeric id.
Note that the value in the call to scrollTop() is corrected for the height of the target element.
for (var i = 0; i < 100; i++) {
// http://www.paulirish.com/2009/random-hex-color-code-snippets/
var randomColor = '#' + Math.floor(Math.random() * 16777215).toString(16);
$("#myScrollingDiv").append('<p>#' + i + ': text <span style="background-color:' + randomColor + '" id="' + i + '">text</span> text</p>')
}
$("#myForm").submit(function(event) {
event.preventDefault();
var idNumber = $("#idNumber").val()
var targetElem = $("#" + idNumber);
var targetOffset = targetElem.offset();
var divScrollTop = $('#myScrollingDiv').scrollTop();
$('#myScrollingDiv').scrollTop(divScrollTop + targetOffset.top - targetElem.height());
});
body {
height: 5000px;
overflow-y: scroll;
}
#myScrollingDiv {
overflow-y: scroll;
height: 100px;
width: 150px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="myScrollingDiv"></div>
<form id="myForm">
<input id="idNumber" type="number">
<input type="submit">
</form>
Enter a numeric ID:
This question, if I understand it correctly, has been already answered here if you are willing to use JS and JQuery. Just attach the code suggestion to a button.
https://stackoverflow.com/a/5267018/5797159
Initially I was trying to change the look of a textarea when it was empty with just CSS. I thought this would work, but as you can see when writing something and clicking the button, the values are different. Does anyone know of a solution for doing this width CSS or JS is required? Could that be possible with an input??
var area = document.querySelector("textarea");
var btn = document.querySelector("button");
btn.addEventListener("click", function() {
var value = area.value;
var attr_value = area.getAttribute("value");
alert("value: " + value + "\nattr value: " + attr_value);
});
textarea {
background: red;
transition: background 0.5s ease;
}
textarea[value=""] {
background: gray;
}
<textarea value="Here I am"></textarea>
<br>
<button>Click me!</button>
Textarea HTML elements do not have a value attribute. Their value is their inner text content.
Thus, the value property will always fetch the correct input value.
getAttribute("value") will fetch the value of the textarea's value attribute, if you give it one. But since this attribute is non-standard on textarea elements, you ought not to use it, anyway.
:)
A solution for your initial question is probably to use a little js snippet, since I couldn't get it to work with :empty either.
http://jsfiddle.net/ciscoheat/hvo3h8vz/
var area = document.querySelector("textarea");
area.addEventListener("input", function() {
if(area.value) area.classList.add('has-content');
else area.classList.remove('has-content');
});
Intro
I am creating a content editor in which I want to add the functionality to choose a word which you would like to be highlighted while typing your content.
At this moment I achieved to search any word chosen in the #dynamicWord and then typed in #contentAreaContainer and give it a red border by adding em around the keyword and style the em trough CSS:
Part of the Code:
<div class="word">
Dynamic word to highlight: <input name="dynamic_word" id="dynamicWord" value="Enter word..">
</div>
<div id="contentAreaContainer" oninput="highlighter()">
<textarea id="contentArea"></textarea>
</div>
function highlighter()
{
var contentAreaContainer = document.getElementById('contentAreaContainer');
var dynamicWord = document.getElementById('dynamicWord').value;
wrapWord(contentAreaContainer, dynamicWord);
};
wrapWord() does:
function wrapWord(el, word)
{
var expr = new RegExp(word, "i");
var nodes = [].slice.call(el.childNodes, 0);
for (var i = 0; i < nodes.length; i++)
{
var node = nodes[i];
if (node.nodeType == 3) // textNode
{
var matches = node.nodeValue.match(expr);
if (matches)
{
var parts = node.nodeValue.split(expr);
for (var n = 0; n < parts.length; n++)
{
if (n)
{
var em = el.insertBefore(document.createElement("em"), node);
em.appendChild(document.createTextNode(matches[n - 1]));
}
if (parts[n])
{
el.insertBefore(document.createTextNode(parts[n]), node);
}
}
el.removeChild(node);
}
}
else
{
wrapWord(node, word);
}
}
}
em{border: 1px solid red;}
The problem:
Now at this moment every time on input in #contentAreaContainer the keyword chosen is highlighted a short period in the #contentAreaContainer, because highlighter() is triggered on input. But it should stay highlighted after finding it instead of only oninput.
I need oninput to search for the #dynamicWord value with wrapWord() while some one is typing;
Any time the #dynamicWord value was found it should permanently get an em
So how can I sort of 'save' the found keywords and permanently give them the element until the dynamic keyword gets edited?
Check the DEMO version
Solved:
Using setTimeout() instead of oninput I managed to make the highlight look constant. The change:
function highlighter()
{
var contentAreaContainer = document.getElementById('contentAreaContainer');
var mainKeyword = document.getElementById('main_keyword').value;
wrapWord(contentAreaContainer, mainKeyword);
repeater = setTimeout(highlighter, 0.1);
}
highlighter();
I removed oninput="highlighter()" from #contentAreaContainer.
You are trying to highlight words in a textarea. As far as I know a textarea does not support html elements inside. If you do it would simply display them as text.
Therefore you need to use an editable div. This is a normal div but if you add the attribute:
contentEditable="true"
the div acts like a textarea with the only difference it now process html elements. I also needed to change the onchange event into the onkeyup event. The editable div does not support onchange events so the highlight would not be triggered. The HTML for this div looks like:
<div contentEditable="true" id="contentArea">Test text with a word in it</div>
Here is the working code in a fiddle: http://jsfiddle.net/Q6bGJ/ When you enter a new character in the textarea your keyword gets highlighted.
However there is still a problem left. You surround the keyword with an em element. This results in surrounding it on every keystroke. Now you end up width many em's around the keyword. How to solve this, I leave up to you as a challenge.