Strange blue border on Firefox - javascript

Please, take a look at this code
http://www.jsfiddle.net/tt13/5CxPr/21
On Firefox it shows strange blue border when you select multiple row by pressing ctrl button but on Chrome it doesn't.
Using latest Firefox 10.0.2.
Is that browser related bug?

This is due to text being selected - native browser behavior.
You can observe the same issue in Chrome as well by using the SHIFT key instead of CTRL.
To overcome this, you can simply clear the selection right after user click the cell to select:
$(".subject").live('click',function(event) {
if(event.ctrlKey) {
$(this).toggleClass('selected');
} else {
$(".subject").removeClass("selected");
$(this).addClass("selected");
}
if (document.selection)
document.selection.empty();
else if (window.getSelection)
window.getSelection().removeAllRanges();
});
Updated fiddle.

Try setting CSS property -moz-user-select to the table to disable the default selection behavior:
table { -moz-user-select: none; }
MDN

This works for current version of Firefox 20.0.1 if you're prepared to add an extra element inside your cell to allow the text to still be selectable.
td { -moz-user-select: -moz-none }
td * { -moz-user-select: text }
http://jsfiddle.net/nukj7/

Related

Click to select all text in div not working on mobile

I want to select all text inside a div via a single click/tap. See example code (jsFiddle):
document.getElementById('target').addEventListener('click', function (event) {
setTimeout(function() {
window.getSelection().selectAllChildren(
document.getElementById('target')
)
}, 100);
});
<div id="target">
<span>click to select all </span>
<span>text</span>
</div>
It works on desktop, but not properly on iOS using Safari (likely same problem on Android as well).
As you can see, I added a setTimeout() in an attempt to capture the mobile tap, but it only works after taping many times or focusing on the div via a long tap.
How can I make it select the full text with a single tap on iOS using pure JS?
Edit 1: Setting touchstart as event trigger might work, but avoiding it as it can be triggered by scrolling down the page and accidentally touching the element.
Edit 2: Making a bounty for a tested solution which works on iOS and mobile in general.
Instead of JS you could use a CSS only approach with user-select: all; (MDN)
#target {
/*
-webkit-touch-callout: all; /* iOS Safari /
-webkit-user-select: all; /* Safari /
-khtml-user-select: all; /* Konqueror HTML /
-moz-user-select: all; /* Firefox /
-ms-user-select: all; /* Internet Explorer/Edge /
*/
user-select: all;
}
<div id="target">
<span>click to select all </span>
<span>text</span>
</div>
Be aware that if you want users to be able to select a custom range within your #target it won't let them do that with this approach as it will "force" an all-text selection. But if that is not an issue/requirement the CSS approach is more elegant (IMHO) and should work cross device/platform (if you need to support really old browsers, you can use vendor prefixes as well).
I actually like #exside's solution, but cross platform support is sadly poor.
Anyways, the solution.
We'll use the window.getSelection api which returns a Selection object and move on from there.
const selectableTarget = document.getElementById('target');
selectableTarget.onclick = () => {
// Get reference to the Selection object and remove all selected ranges
const selection = window.getSelection();
selection.removeAllRanges();
// Create a new range and select the target node
const range = document.createRange();
range.selectNode(selectableTarget);
// Add the range to the selection
selection.addRange(range);
};
<div id="target">
<span>Select me please</span>
</div>
You can try window selection APIs or document.selection API for old browsers: -
document.getElementById('target').addEventListener('click', function (event) {
if (window.getSelection && document.createRange) { //Browser compatibility
sel = window.getSelection();
if(sel.toString() == ''){ //no text selection
window.setTimeout(function(){
range = document.createRange(); //range object
range.selectNodeContents(event.target); //sets Range
sel.removeAllRanges(); //remove all ranges from selection
sel.addRange(range);//add Range to a Selection.
},100);
}
}else if (document.selection) { //older ie
sel = document.selection.createRange();
if(sel.text == ''){ //no text selection
range = document.body.createTextRange();//Creates TextRange object
range.moveToElementText(el);//sets Range
range.select(); //make selection.
}
}
});
jsfiddle: https://jsfiddle.net/u4yhn3sk/41/

How do you scroll to the position of the cursor in a textarea?

JS Fiddle Demo
HTML
<textarea rows='5'>
sdfasjfalsfjasf;klasdfklaksdfkjlasdfkjlasdjkfadls;fjklasdfjklasdkjlfaskljdfkalsjdfjlkasdfkjlasdkjlfasfkl;ajklsdfjklasdfkjlaskjldfaskjlfkljsadkjlfaskjldfkjlasdfkjlasdjklfaskljdfkjlasfkjlasdkjlfasjklfajklsdfjklasdfjlkadjsdfasjfalsfjasf;klasdfklaksdfkjlasdfkjlasdjkfadls;fjklasdfjklasdkjlfaskljdfkalsjdfjlkasdfkjlasdkjlfasfkl;ajklsdfjklasdfkjlaskjldfaskjlfkljsadkjlfaskjldfkjlasdfkjlasdjklfaskljdfkjlasfkjlasdkjlfasjklfajklsdfjklasdfjlkadjsdfasjfalsfjasf;klasdfklaksdfkjlasdfkjlasdjkfadls;fjklasdfjklasdkjlfaskljdfkalsjdfjlkasdfkjlasdkjlfasfkl;ajklsdfjklasdfkjlaskjldfaskjlfkljsadkjlfaskjldfkjlasdfkjlasdjklfaskljdfkjlasfkjlasdkjlfasjklfajklsdfjklasdfjlkadjsdfasjfalsfjasf;klasdfklaksdfkjlasdfkjlasdjkfadls;fjklasdfjklasdkjlfaskljdfkalsjdfjlkasdfkjlasdkjlfasfkl;ajklsdfjklasdfkjlaskjldfaskjlfkljsadkjlfaskjldfkjlasdfkjlasdjklfaskljdfkjlasfkjlasdkjlfasjklfajklsdfjklasdfjlkadj
</textarea>
<br />
<button id='scroll-to-cursor'>Scroll to Cursor</button>
JavaScript
$('#scroll-to-cursor').on('click', function() {
// ?
});
Desired Outcome
Click somewhere in the textarea to place cursor.
Scroll away so cursor isn't visible.
Click "Scroll to Cursor" button.
Textarea scrolls to the position of the cursor
Note: I'm using jQuery.
The only way I could figure out how to scroll is to use jQuery's scrollTop
function. It sets the scroll position to "the number of pixels that are hidden from view above the scrollable area".
I've diagrammed the problem below. Passing in the length of that red line (in pixels) to scrollTop should do the trick. But I can't figure out how to get the length of the line.
textarea.blur()
textarea.focus()
Does the job.
Example: https://jsfiddle.net/syy25x69/
To select a text in IE see: Set textarea selection in Internet Explorer
Update
In order for this to work, I noticed that the selection must be collapsed. You can restore the selection later if you need to.
// collapse selection here
textarea.blur()
textarea.focus() // this scrolls the textarea
// expand selection here
Another example: https://jsfiddle.net/rk8cL174/
From Jonathan Levine's comment, I realized that this answer works for me.
Fiddle Demo
JavaScript
$('#scroll-to-cursor').on('click', function() {
$('textarea').focus();
$.event.trigger({ type : 'keypress' }); // works cross-browser
// new KeyboardEvent('keypress'); // doesn't work in IE and Safari
/* var evt = document.createEvent('KeyboardEvent');
evt.initKeyEvent('keypress', true, true, null, false, false, false, false, 0, 32);
$textarea.dispatchEvent(evt);
evt = document.createEvent('KeyboardEvent');
evt.initKeyEvent('keypress', true, true, null, false, false, false, false, 8, 0);
$textarea.dispatchEvent(evt); */
});
/*
To test:
1) Click somewhere in the textarea to place cursor
2) Scroll away so cursor isn't visible
3) Click "Scroll to Cursor" button
*/
Explanation
When the user presses a key, the browser does two things:
Places the key in the position after the cursor.
Scrolls to that position.
This solution just simulates that (without actually entering any text).
Edit: The old solution isn't standards compliant. initKeyEvent is deprecated. The update only uses the KeyboardEvent() constructor, which is compliant and works in all browsers except IE (Safari is a question mark).
Edit 2: Using $.event.trigger({ type : 'keypress' }); instead of new KeyboardEvent() works just as well, and works in all browsers.
For some weird reason, Chrome only scrolls when there is a caret on the textbox, not when a selection is active, so if you need to scroll to a selection, do this little hack:
// set the single caret first
textarea.setSelectionRange(index, index);
// focus the textarea box so the scroll happens
textarea.focus();
// now do the selection
textarea.setSelectionRange(index, index + x);
This is my spin on things.
I found that Audi Nugraha’s solution worked when testing, but not when I tried it in an Electron application.
A solution which did work for me was to position the cursor to the beginning and then blur/focus.
textarea.selectionEnd = textarea.selectionStart = position;
textarea.blur();
textarea.focus();
I have incorporated the above into a function:
function scrollTextarea(textarea,position) {
textarea.selectionEnd = textarea.selectionStart = position;
textarea.blur();
textarea.focus();
}

Raphael JS - Prevent text highlighting when clicking

DEMO: http://jsfiddle.net/p7Lze6nh/
Using Raphael JS 2.1.2 and I'm trying to disable text highlighting when an element is clicked. It does it on Chrome, but not on IE for some reason. I don't have FF on this laptop at the moment to test.
The code is relatively straightforward-
var paper = Raphael(0, 0, 125, 125);
paper.canvas.style.backgroundColor = "Black";
var a = 0;
text1 = paper.text(10, 10, a).attr({"text-anchor":"start", fill:"white"});
rect1 = paper.rect(10, 50, 50, 50).attr({fill:"white"});
rect1.click(function(){
inc()
});
function inc() {
a++;
text1.attr({text: a});
}
I've tried using the 'user-select: none' and other various CSS rules found via examples for the div containing the paper, but that didn't work. I've also tried using
text1.userSelect = "none";
...and the others directly into javascript, but I didn't get anywhere, either. I recall Cookie Clicker having this problem, but I can't seem to find the solution in the code. But, it also uses canvas instead of Raphael.
User select should work ok, but not in the format shown. You can't just set an object variable like that.
Using css styling, it can be done like this...
text {
-moz-user-select: none;
-webkit-user-select: none;
}
jsfiddle
and slightly different version setting class direct...
.donthighlight {
-moz-user-select: none;
-webkit-user-select: none;
}
text1.node.setAttribute("class","donthighlight");
jsfiddle
I guess be wary some older browsers may not support this, which is a reason Raphael is often used, and extend the css to include the other browsers.

Issue in Chrome, removing CSS with jQuery stays in chrome

I'm currently working on a table application heavily coded in javascript using jQuery.
When you click on a td cell jQuery pushes 2px solid black to the border property. Then on blur I remove the style attribute with removeAttr to make it revert back to the stylesheet settings. Works fine in IE9, but when I test it in Chrome, the left border resizes, but stays black.
The only thing that seems to get rid of this is opening the console. When I blur with the console open the style tag removes so I don't understand why it's still rendering a black border on the left. Any ideas?
EDIT: I've made a video showing the problem I'm experiencing.
http://www.youtube.com/watch?v=JCmYNOO5u4I
Here's the code:
$("td.display").live('mouseenter', function () {
$(this).addClass('selected');
}).live('mouseleave', function () {
$(this).removeClass('selected');
});
The CSS is:
table TD.selected {
border: 2px solid;
border-color: Black;
}
Rather than using $.removeAttr, use $.css to restore the CSS. $.removeAttr isn't going to work properly due to how CSS persists, most likely.
What you should really do is add a class on focus, then remove that class on blur. That is, $.addClass and $.removeClass, documented at the respective links.
Instead of using JavaScript to achieve this trivial effect, use CSS. The :hover pseudo-selector is well-supported in all modern browsers.
td.display:hover {
border: 2px solid black;
}
I have adjusted your selectors, since <td> elements are always contained in a <table> element.
Demo: http://jsfiddle.net/JKM7e/
Update
This is one of the many table-css-related bugs in Chrome. A work-around is to initiate a re-render. To solve the issue, let Chrome render the page again. This fix should not activate in non-webkit browsers, so an additional variable is added.
I've also optimized your code, and replaced the deprecated live with on. The new revision can be found here.
// true if webkit, false otherwise
var isWebkit = !!$('<div style="-webkit-border-radius:1px">')[0].style.cssText.length;
$(document).on('blur', 'input.editCell', function () {
var $thisParent = $(this).parent(); // <-- Optimizing by caching
// Remove Highlight and bold around cell
$thisParent.removeClass('selected');
var colRow = $thisParent.attr('id').split('_');
$('th:containsExactly(' + colRow[0] + ')').removeAttr('style');
$('td.yAxis:containsExactly(' + colRow[1] + ')').removeAttr('style');
// Change class back to display
$thisParent.attr('class', 'display');
// Take the entered value and put it in the cell
$thisParent.html(this.value);
// if(isFunction(this.value) === 'SUM')
if (isWebkit) { // Fix for Webkit bug: render the table again
// Without jQuery, for efficiency
var style = document.getElementById('spreadsheetTable').style;
style.color = '#111'; //<--1. Change style
setTimeout(function(){style.color='';}, 4); //<--2. Fix
}
});
Two options:
- instead of removeAttr, reset the style with .css()
- use a class instead, and use toggleClass() in the focus and our events
The second option is definitely preferable.

Is possible to exactly find position of KeyPress event in browsers except IE?

From my recent question, I use KeyPress event for detecting '#' character in rich text editor. By the way, I just found that KeyPress event in other browser like Firefox 3.5 and Google Chrome 4 do not return any position in this event.
For clarify, my position is a distance from top or left of screen. In this case, it should be distance between new character and IFrame screen. In IE, I can find it in event object like x, y, offsetX, offsetY.
Is possible to find position from last character that was typed? Or you have any other idea for finding it.
For an input/textarea, you can find out the current position of the cursor using input.selectionStart/selectionEnd. If it was a simple insertion keypress that will be just ahead of the new character. (Don't rely on it, there are browsers that support neither the IE nor the Mozilla extensions.)
If your ‘rich text editor’ is a HTML designMode/contentEditable thing (the horror!) then I would guess you'd have to use window.getSelection() to read the position of the cursor. This is even worse:
if (window.getSelection) {
var selection= window.getSelection();
if (selection) {
if (selection.getRangeAt) { // Mozilla
if (selection.rangeCount>=1) {
var range= selection.getRangeAt(0);
return [range.startContainer, range.startOffset];
}
} else if (selection.focusNode) { // Webkit
return [selection.focusNode, selection.focusOffset];
}
}
}
Seems to work with designMode for Mozilla, haven't tested in the others.

Categories