How to make a contenteditable div reversible after change made with js? - html

When I delete some text in the contenteditable div in mistake, I can reverse it with Ctrl + z.
But after I made some change with javascript. I can't use Ctrl + z to reverse to previous change.
For example, when I add node to the selected text ,like <p>or <h1>, I could not reverse the content to previous change.
jsfiddle.net/NfGM3/
(bad coding because I am new to window.getSelection())
I use div instead of textarea because I want to add some node into the content.
So, how can I make it reversible in contenteditable div after change made with js ?

What about adding a keyup event handler that will keep track of the current text after every keyup. You can then trap Ctrl+Z and revert back to the previous content if you detect that Ctrl+Z have been pressed.
You could potentially keep revisions in an array to support a series of Ctrl+Z operations.

Related

Restricting typing at a distance from the end on an input field

I have an input field, at the end of which i've created a character counter:
The problem is that now, it is possible to type beneath the counter which is no good:
I would like the typing area to be restricted a certain distance before the end of the input field, something like this:
I am aware of maxlenght but since the letters have different lengths i.e. you can fit 183 "i" but only 57 "W", which would make for a really unintuitive typing experience, if your typing is cut off at the middle of the field.
The two possible solutions that occur to me.
1.
Simply shortening the input and positioning the counter next to the input, then styling a common parent element to look like the input. This is the more simple and less error prone solution.
2.
This way is a bit more complicated, but basically what you would do is create a hidden element somewhere (NB not display: none;) with the same font size/weight/family and attach a keydown event handler to the input field.
In this handler you copy the contents on the input to the hidden element, measure the width in pixels and compare that to your input. If the difference is too small, you return false in your input handler, making sure you're not preventing the user from pressing delete or backspace first.
It should be noted however that this method is pretty difficult to get right and I would consider it to be the "dirty" solution.

Is it possible to add paragraph spacing inside of a textarea?

Just wondering if anyone has any ways of adding paragraph spacing visuals to text inside a textarea via CSS, or even JS?
I'm aware of line-height but would like to add the impression of spacing before/after paragraphs themselves inside of a textarea, instead of having to hit enter twice inside the textarea to get a space between paragraphs.
Is this possible with a textarea alone or do I need to consider rich text editors, or maybe even writing a simple text editor myself with paragraph spacing? (I'd rather not go this route as I am merely after paragraph spacing, not all the additional formatting options that comes with text editors)
Nope. Without the line-spacing property you cannot add space between paragraphs in a textarea without altering the value of the area. This is not something that JavaScript or CSS selectors can do.
Yes, it should be possible with JavaScript by replacing the value of the textarea while listening for keyboard event values, specifically for the Enter key.
You store the value in a variable, and whenever a user hits enter (its event value is 13), it takes that text and adds a new line to the end. Now that becomes the value stored in the variable, and a new line is added the next time the user hits enter, and so on.
Here's an easy implementation if you're already using jQuery:
$('#my-text').keypress(function(e) {
if(e.which === 13) {
var text = $('#my-text').val();
$('#my-text').val(text + '\n');
}
});
e is the keyboard event passed in as a parameter, and when that happens to be an enter key, the code stores the text value and then replaces the value of the textarea with that value plus a new line.
Here's a demo on codepen:
http://codepen.io/denmch/pen/qNyjZE

Is there a way to inform the screen reader about a transition to a new section on the same page?

I have a page that has 2 steps to register a user.
After a user has filled out all fields of the first section, he needs to confirm the "Terms and Conditions" and press a button to confirm it.
After he has pressed the button, first section is becomes readOnly and the second section (more fields to fill) appears at the bottom of the page and the page does a scrollTo this new section.
I need to inform the screen reader that there is a new section on the same page but I don't know who can I do it.
I appreciate your help!
In your html have an empty span/div with aria-live="assertive". In your button click function, add the text you want the reader to announce to that span.
(This is the same function where you will be taking focus to that section.)
Don't forget to empty it outside the function to make it announce properly next time also.
Aria-assertive text will be announced each time it is changed.
Eg.
In HTML
<span id="announce" aria-live="assertive"></span>
<button id="btn">Click</button>
In javascript
$("#btn").click(function(){
$("#announce").text("Scrolled to a new section");
});
This is about focus management. You need somewhere to anchor focus that makes sense to the user and you need to then move that focus.
This is not an ideal solution overall, but lacking context for the larger objective I'll give you the bits to get this part functional / useful.
First, add this style so you can see where the focus is going (you can remove/change it later):
*:focus {
outline: 2px solid #f00;
}
Now as you tab through the page you can see where the focus lives.
Then in your script where you create the new form (I recommend you actually just hide this section and display it instead of writing it in via JS, but I understand this may be a demo), update the <h3> to be focusable by adding an id attribute and then a tabindex so that you can drop focus on it. I use the <h3> you already have since it provides the context for the user and in this case overrides my general distaste for using tabindex on non-interactive elements.
<h3 id="second" tabindex="0">
Then add bit of script after your setTimeout() that moves the focus to that element (thereby ensuring it has been rendered and can receive focus):
var secondForm = document.getElementById('second');
secondForm.focus();
Now when you click the "Continue!" button, the page scrolls and the heading will receive focus, get announced (you can add instruction text, etc), and the user may continue.
You will probably need to massage the script a bit, maybe stuffing it in its own timer function to be certain it only fires when you want, but overall the general concept is in there.
I made a pen to demo it.

How to make a custom web component focusable?

I'm writing a custom web component that is meant to be interactive. How can I tell the browser that this custom component should receive focus?
I wish that my custom element…
could be focused (by tab-navigation);
could receive keypresses when focused;
could be matched by :focus pseudo-selector.
I'm not using any external library, just plain HTML5 APIs.
Based on this demo that I found in this question, I have this answer:
Just add the tabindex attribute to the elements you want to be focusable.
// Add this to createdCallback function:
if (!this.hasAttribute('tabindex')) {
// Choose one of the following lines (but not both):
this.setAttribute('tabindex', 0);
this.tabIndex = 0;
}
// The browser automatically syncs tabindex attribute with .tabIndex property.
Clicking on the element will give it focus. Pressing tab will work. Using :focus in CSS will also work. keydown and keyup events work, although keypress doesn't (but it's deprecated anyway). Tested on Chrome 44 and Firefox 40.
Also note that this.tabIndex returns -1 even if the HTML attribute is missing, but this has a different behavior than setting tabindex="1":
<foo></foo>: No tabindex attribute, the element is not focusable.
<foo tabindex="-1"></foo>: The element is not reachable through tab-navigation, but it is still focusable by clicking.
References:
http://www.w3.org/TR/html5/editing.html#sequential-focus-navigation-and-the-tabindex-attribute
https://html.spec.whatwg.org/multipage/interaction.html#the-tabindex-attribute
https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/tabindex
https://github.com/whatwg/html/issues/113
#Denilson, I would like to provide you with some more information.
As you said, this.tabIndex = 0 works when your webcomponent contains no focusable elements. If it does, it gets more complicated.
For example, if your component contains one or more inputs, then first the "whole" component gets focus, and only later, when tabbing, each inner inputs get focus, one by one. This is usually not what you want. Usually, when the component gets focus this should mean its first input gets focus immediately.
Also, there is a reverse tabbing problem. If your first input has focus and you press SHIFT-TAB, then the "whole" component gets focus, and you are forced to press SHIFT-TAB twice to move to the previous element.
I found this to solve all focus and tabbing problems:
// At first, the component may get focus and accept tabbing.
createdCallback = function () { this.tabIndex = 0; }
// When the component gets focus, pass focus to the first inner element.
// Then make tabindex -1 so that the component may still get focus, but does NOT accept tabbing.
focus = function (e) { firstFocusableInnerElement.focus(); this.tabIndex = -1; }
// When we completely left the component, then component may accept tabbing again.
blur = function (e) { this.tabIndex = 0; }
Note: As of now (Sep 2015) if an inner element gets focus, then the "whole" element is not matched by the :focus pseudo-selector (tested only in Chrome). If find this behavior to be just plain wrong. The focus event was fired, and the blur event was not. So the element should have focus, right? I hope they change this in the future.
Short answer: delegatesFocus is what you need here, not tabindex.
Details:
Assuming that you have interactive elements inside the shadow DOM, there is no satisfying way to make the component programmatically focusable with tabindex:
if you set it to 0 you add the host element to the tab sequence ("sequential keyboard navigation") and you have an extra tab stop
if you set it to -1 you remove not only the host element but any interactive element inside its shadow DOM from the tab sequence, so the whole thing becomes inaccessible for keyboard users
There's a web component API just for this: ShadowRoot.delegatesFocus, see here. Set this to true and you'll get:
calling .focus() on the host or clicking on any non focusable part of the component focuses the first focusable element in the shadow DOM
:focus styles are applied to the host in addition to the focused element within
tab sequence is unchanged (it should already work the way you want)
It's supported since shadow DOM v1.
One very pragmatic approach I use, if possible and suitable, is just to put a <button type='button'> around my custom element.
This maybe does not fit as solution for you, I mention it anyway for others stepping into this question / problem.
It handles all focus matters, including a focus rectangle an so on.
To tame a <button> is less work than it seems (think especially about the line-height the button changes)

Perform double click on html element

I want to perform double click on an html element. I can click once, but can't double. I tried to move mouse on element, but couldn't find coordinates.
...
IE.Document.GetElementById(An & "q8").focus
IE.Document.GetElementById(An & "q8").dblclick ' not working on hmtl
...
I can't add, change etc. html codes. So I can't add or change events, attributes. I need to doubleclick on element directly, maybe mousemove and click or something like that.
Double click action selects a value from a popup list, and set it to a inputbox. Keystrokes not working. Client side changes are not applied. I tried to change input value, but when another element's value changes first one returns to original value.
(vb6 and ie8+)