Keep text input scrolling synchronized - javascript

This one's a challenge:
Suppose you have two text inputs, as in this fiddle. When the user "scrolls" inside of one (e.g. by moving the cursor to the far right or left), I'd like to "scroll" the other so that it stays in sync. Can this be done, at least in modern browsers?

I would change the text that isn't being input to an IFrame. If both need to be inputs, then dynamically switch your element from iframe to input when it is focused on/away from.
In the input box, you can find where the caret is by using the selection properties; then the IFrame can then be scrolled using scrollTo.
I'm afraid I don't have a complete solution for finding out exactly the scroll state of the input box.

Related

Highlight certain words in input form without using tags?

I need to highlight certain words in Twitter input form as user types their tweet but apparently Twitter has a script that protects the form and removes any HTML tags that I put in there. Is there any way to do this without using tags?
The only way I can think of is to use getBoundingClientRect() and draw an overlay over the box while the user is writting.
getBoundingClientRect() is expensive, but running at user typing speed is no problem actually.
It will return the absolute position of the element from the top/left margin of the window, so you can create an absolute (or fixed I guess) element over the box and set the received position to your elements.
I guess that the fastest way is to process the text and create HTML tags like you do now, and then get the getBoundingClientRect() and create the overlay of each tag. Twitter then will reset the input to whatever it wants, but you already got the getBoundingClientRect() as long as you do that in the same event loop when you create your tags (before Twitter modify nothing).
IMPORTANT: Don't forget to add pointer-events CSS to none so no mouse clicks are catch by your overlay.
pointer-events documentation here
getBoundingClientRect documentation here

Select text in contenteditable after it has changed

I am about to write a input system for a web application that is a bit more complex. We have Labels in our text that are weather displayed as a bootstrap label (when the contenteditable div is blured) or displayed as handlebars e.g. {{firstname}} when the text is focused.
The changing in states is done by jQueries $().html(content) where I change the content based on the source when I focus the text field.
The problem is: if I click the text, I don't want to need to click a second time to place the cursor, because the text changed. It works as long I don't click inside of a tag but inside the contenteditable root element. but if I click inside of a tag inside the contenteditable, the cursor is not set.
my idea was to get the mouse position when clicking the contenteditable and then set the text cursor to exact that position when I have changed the text. But while I know, how I set the cursor to a specific offset inside a text node, I have no clue how to get this necessary offset when clicking. any ideas?
Edit: Here is the behaviour in a little screencast: https://youtu.be/RZvHxxM6wsQ
Edit2: Here is the problem reproduced on the smallest kind of working example:
https://jsfiddle.net/8z5Lnxef/3/

How to detect if there is text in textarea tag under a rect shape div?

Here is my situation as you see in the picture. I am working on a markdown editor. A floating command button panel is visible, when mouse over the textarea. The command button panel is absolute positioned at the top right corner of the textarea.
But some times, text in textarea is blocked by the command panel, making selecting the text underneath it impossible.
I'd like to detect a situation when there is a text under the command panel, then apply a class to shift command panel up 50px.
Here is my question: How to detect if there is text in textarea tag under a rect shape div?
Thanks!
AS you can see in the below picture, the command panel hovering over textarea blocks the text. I'd like to detect this situation.
So, one thing that you can do is get the width of the text area. AKA the cols attribute of the textarea.
Once you have the width of the text area, you get the text (textarea value) within the text area and find the length of that text. If the length of the text within the textarea is greater than the number of cols you know that the text will span the length of the textarea.
One very apparent caveat is that lets say you are writing a poem or something and the text never spans the length of a full line, that length will be longer than the number of cols while never actually spanning the full length of the textarea
Another inherent issue is that if you start scrolling in your textarea new text may come underneath the controls.
I don't really think it would be possible to detect whether or not text inside of a textarea is underneath a certain div.
What I would probably suggest doing is just always have the controls div 50px higher than the textarea. Simple solution, that will still look good and won't require any crazy coding on your part, because I can't really picture an easy way (or any way for that matter) to do this.
Hope this helps.
Ok, I've had to do something similar for a resizing textarea in the past. The secret is to have an offscreen input or textarea with variable width. As the text is updated in your visible text field, copy the text over to the off screen element element. The shadow element has to have all of the same styling that affects the visible element (padding, border, width, height, font size, etc) to make sure you get accurate results. Then measure the width of the shadow element on each text change.

JavaScript/jQuery: Is there any way to use a function on a table only when it is in focus?

I'm really new to JavaScript, haven't even finished the track on Codeacademy yet. But I did finish jQuery, HTML/CSS, and Python so the logic at least isn't completely foreign to me...
Anyway, I made a testing page to try to practice my JavaScript skills for the first time, what I ended up doing was making a "color selection" div that will change to different colors when you click on it and then a large table full of different cells that will change to the color of the "color selection" div when the mouse hovers over it. So basically a very simple coloring board. But the way it is, you can't just click on the canvas and start coloring, it'll change colors anytime your mouse enters that part of the screen whether you selected it or not.
The "canvas" itself is just a large table. And if I'm understanding correctly, I can't just use .focus() on a table.
So I guess to put it simply... what I'm wondering is if there is any way to say "when this table is in focus, do X when the mouse hovers over (this)".
Or else, "when the user clicks in this table, make these cells change color when the mouse hovers. But when the user clicks outside of the table, stop doing that."
Is this even a possibility or did I go about this all in the wrong way?
Maybe try this:
SEE DEMO
$('#myelem').attr('tabindex',-1).hover(function () {
if (document.activeElement === this) {
console.log('hover');
}
});
Setting tabindex attribute is for crossbrowser support of focus event as in some browser, by default without setting tabindex, some html element don't natively support focus.
BTW, if you don't want focused element to be restyled by browser, you could add this css to the elements:
$('#myelem').css('outline',0).attr('tabindex',-1).hover(function () {...});

How can I temporarily prevent a scrollable div from scrolling?

Here is my current situation:
I have a web page containing a couple scrollable divs. Each of those divs contains a number of objects. I am using YUI to display popup menus of actions that can be performed on each object. Each object has its own menu associated with it that is constructed and displayed dynamically. The popup menus can be large and can overlap the bounds of the scrollable div.
From what I believe are issues with focus (the menus must be accessible), when I hover the mouse over an action that lies on top of an edge of the scrollable div, the div automatically scrolls, moving the content but leaving the menu stationary. Trying to move the menu dynamically when this happens is not something I want to do as I believe it would provide a poor user experience.
So I need to prevent this focused menu from scrolling the div. My idea for providing the best user interface is to prevent these inner divs from scrolling when a menu is open. This leaves the menu positioned in the optimal location to show the user which item is being acted upon. If the user wants to scroll the box, they can click to close the menu and then scroll normally.
How can I do this? I need a solution that works across the major browsers.
My first thought was to listen to the onscroll event for that particular element. Unfortunately, there does not seem to be an easy way from there to just prevent the scrolling from happening. For one, my JavaScript event code appears to execute after the actual scrolling has occurred.
Then, I thought that since my code is being run after the object has scrolled, I could just reset obj.scrollTop and obj.scrollLeft. Sure enough, this appears to work, though I am worried that on slow browsers the user will see the content inside the div "jump around". Also, it would be really nice if the amount the element scrolls is part of the event object. Is it stuck in there somewhere? I'm looking for an alternative to having to store the scrollTop and scrollLeft variables for this element and then using them while the scrolling is temporarily disabled.
What is the best way to solve this entire problem?
I agree with Anthony regarding the presentation of the functionality you're trying to disallow. If you're going to disable scrolling, then you should make that part of the page visually disabled or removed.
To that end, you can position a semi-transparent div on top of the scrollable div in question, which would capture the mouse events and visually show that the scrollable div is inactive for now. It would be hard to make cross-browser compatible and wouldn't be perfect, but then again very few client-side tricks like this are.
The simple answer is no you can't do this. Its doubly no if you want a cross-browser solution.
Providing the user with the clear affordance that something can be scrolled then denying them that is just plain poor UI design.
Ok so after your edit it turns out you are not actually trying to prevent the user from scrolling.
The main answer remains true though. It sounds as though the focus is going to rectangle (probably an anchor?) that is not fully in view and causes a scroll. Is there a reason this rectangle must get the focus? For accessibility?
What if you didn't have overflow: scroll and instead you used overflow: hidden and provided scroll up/down buttons that allowed the user to scroll when necessary? These buttons could of course be disabled easily.
Though it may not be the answer you are looking for, if you are to set the display value of the div to 'none' while the page loads (from the server) and then have an event wired to the page load (either pageLoad in ajax.net or attach it to the onload event via javascript) that will make the div display set to 'block' .. that would ensure that slower browsers wouldn't see the div 'jumping around' (could even put a 'loading' image in the div to show users it's doing something and not just invisible)
sorry i couldn't provide a more complex/fluent solution.
I found a way to work around this issue. By removing the menu element from the scrollable div and then appending it directly to document.body, the browsers all stop trying to scroll the div to reveal the focused element (even though the element is already completely visible).
Thanks to all for your time and your answers!

Categories