React Cursor jumping when formatting textfield - javascript

I know there are a lot of topics on this, and I've done my best reading and implementing their solutions, but I just cant get it to work properly
Im trying to format the phone number so that it displays in a certain format.
I created a demo of how it works in my app.
https://codesandbox.io/s/dank-leaf-94s3w?file=/src/App.js
Edit: sorry to describe the issue a bit more.
everything works fine when you are just typing out a # front to back
but when I try to modify the middle numbers the cursor will jump to the end after each input.
Thanks

Hi so the problem is that you pass a new value and that will be just like inputing the whole value. And this will cause the cursor to move to the end.
You can overcome it by requesting a window animation frame and move the cursor back to where it was:
const caret = target.selectionStart;
const element = target;
window.requestAnimationFrame(() => {
element.selectionStart = caret;
element.selectionEnd = caret;
});
Here is a copy of your sandbox.

You are passing the ref into the wrong element. In #material-ui/core/TextField you must pass the ref to the inputProps instead of direct ref.
Just change the:
ref={input}
to:
inputProps={{ ref: input }}
There are other issues in your code such as not parsing the value to the normal string state but the issue for jumping was for ref

Related

Draft.js applying styles to many individual characters

I have been trying to tailor Draft.js into a sortof IDE with custom syntax highlighting, I am aware Prism exists including Prism for Draft.js but it lacks the features I require. I am not using Draft.js in the manner that is expected but it feels like it is something it should be able to handle.
In the Draft.js page Complex Inline Styles under Model they show an array of styles and while it is labelled as a "Model" and "In essence", it feels like that it may be possible to do something like that.
I have initially gone the route laid out in this thread Draftjs apply inline styling to text programatically however potentially every character is going to have a different style to the next and it isn't practical to do this for every character potentially on every key press. But generating an array of styles would be really easy to manage.
The documentation for Draft.js feels incomplete and I keep coming to dead ends whichever route I go, such as that there's no OrderedSet page. I know I'm meant to show code that I've tried but it's mostly that SO thread I've tried but moved it into an onChange function and made it work with onChange as well as toggling styles, I included it but I'm pretty sure I'd be told off for not providing anything.
I'm completely stumped and a little frustrated, there's probably a method there I'm looking for but I just can't find it.
const onChange = e => {
const selectionState = e.getSelection();
const newSelection = selectionState.merge({
anchorOffset: 0,
focusOffset: 1,
}); //Selects the first character of the line that was edited
const editorStateWithNewSelection = EditorState.forceSelection(e, newSelection);
const editorStateWithStyles = RichUtils.toggleInlineStyle(editorStateWithNewSelection,'red'); //There's no method to even just set a style, only toggle
const editorStateWithStylesAndPreviousSelection = EditorState.forceSelection(
editorStateWithStyles,
selectionState,
);
setEditorState(editorStateWithStylesAndPreviousSelection);
}

Chrome Address Bar Javascript produces different effect than Console

Trying something new, I was attempting to highlight text on this wikia page using javascript within the address bar (i.e. using "javascript:[code]").
When running the following code sample through Chrome's console, it produces the desired effect. When running it from the address bar, it results in only the affected text -- the rest of the page body is removed.
javascript:txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;index = txt.innerHTML.indexOf(", but")+2;txt.innerHTML = txt.innerHTML.substring(0,index)+"<span style='background-color:yellow;'>"+txt.innerHTML.substring(index,index+40)+"</span>"+txt.innerHTML.substring(index+40);
Note: if you want to try this you will have to manually type javascript: into the address bar before pasting the code, as Chrome automatically removes it.
I'm curious as to why this would be, and also if there is a way to stop the address bar from removing the rest of the page body. Can anyone offer insight?
Thanks.
The quick solution to the problem you're experiencing is to add false; to the end of your query. This will prevent Chrome from removing the text from your page and should give you the result you expect.
Here's the fixed code:
javascript:txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;index = txt.innerHTML.indexOf(", but")+2;txt.innerHTML = txt.innerHTML.substring(0,index)+"<span style='background-color:yellow;'>"+txt.innerHTML.substring(index,index+40)+"</span>"+txt.innerHTML.substring(index+40);false;
To fully answer the question, let me quickly explain what is happening. I'll start by splitting up your JS a bit to make it easier to read.
txt = document.getElementById("Ballas.27_Rebellion_and_Allying_With_Hunhow").parentElement.nextElementSibling;
index = txt.innerHTML.indexOf(", but")+2;
txt.innerHTML = txt.innerHTML.substring(0,index) +
"<span style='background-color:yellow;'>" +
txt.innerHTML.substring(index,index+40) +
"</span>"+txt.innerHTML.substring(index+40);
What you'll note is that the final statement is an assignment operation. In JavaScript the result of an assignment operation is the value of the assignment. In other words, if we say return x = 1 we will both set the value of x to 1 and return the value 1.
This brings us to the reason why Chrome is replacing your page content. The JavaScript you're providing is returning the content of the txt element (the paragraph you're deciding to highlight) and this is then being treated as the content of your new page, the same way that visiting data:text/plain,hello world or javascript:"hello world" in your browser will show the text "hello world"even though you haven't explicitly visited a website.
To fix this, you can return a falsey value in JavaScript - this means any one of the following:
0
false
[]
null
undefined
Hence, adding false; at the end of your JavaScript will have Chrome run the code but not show the resulting text and will prevent it from changing the page content on you unexpectedly.

React catch and remove line breaks or new line when pasting into input field

My input field is just an input field and not an input box and the inherited fact that you can't create new lines inside it is what I want and as intended.
I'm foolproffing my app.
If a Jhon Dumb ctrl-V's text containing a new line (OR ANY OTHER CONTENT THAN MY RULESET) how do I prevent it from triggering update events and fall into the !== '' case?
RULESET :
const validator = /^(?!.*\.\.)(?!.*\-\-)(?!.*\.$)[^\W\_][A-Z0-9\.\-\_]{0,50}$/igm;
const allow = validator.test(inputValue);
if (allow) {
...do stuff
}
I've tried this (placed above validator) :
const inputValue = event.target.value.replace(/\n/g, '').toUpperCase();
which I picked up from here : regex - replace multi line breaks with single in javascript
but inputValue, after going through it was still not === '' (and as it happens valid) so the UpdateInput code still got executed.
if it executes with content it can display that's fine.
but right now the result is that the user gets visual feedback that his input is updating but it's content is empty. (obviously. but I can't say who's intervening here and how we're getting from MY_INPUT\n to ====> (as a matter of fact I'm curious to know why it's doing that) ).
Perhaps this is react already filtering out incorrect input but in that case I need a way to prevent any code from executing at all.
Ideally though I'd "correct" the user input, though.
TO CLARIFY :
this is ONLY in a CTRL-V scenario. enter key does nothing when you are just typing into the input as intended.
thanks!
Input elements should already strip \n from any text.
From MDN
A single-line text field. Line-breaks are automatically removed from the input value.
If the problem is that you're checking against '' and it's failing, then perhaps you need to use the .trim() method.
if (inputValue.trim() !== '') {}
Which could be shortened like:
if (!inputValue.trim())
since empty string is falsey, if that matches your style.

Getting current sentence using Office Javascript API

Using the Office Javascript API, I want to be able to select the current sentence in Word. By current sentence, I mean identifying where the caret position is, then iterating from that position to get the full sentence.
However, looking at the available API calls (such as getSelectedData), this does not seem possible, as there doesn't seem to be a way to get the current caret position.
I know when creating a C# project, you could use 'Microsoft.Office.Interop.Word.Range' and 'Selection.Range' to get a range, which you could use as a caret position.
Am I wrong or can you not get the caret position using the Javascript API?
Late but maybe still helpful for someone:
You can achieve this by combining getSelection() and getTextRanges([separators])on a document - this expands the current selection in both directions, until any of the characters in the list of separators is found.
Documentation for getTextRanges: https://dev.office.com/reference/add-ins/word/range
Example (typescript):
Word.run(context => {
let sentences = context.document.getSelection().getTextRanges(['\n', '.', '?'], false);
context.load(sentences);
context.sync().then(() => {
console.log(sentences.items);
}
return context.sync();
}

How can I perform a double click on an element with Protractor?

I would like to double click on an element but I could not find a way to do this in the document API. I found some references dating back to 2013 but I know things have changed a lot.
Can someone help and tell me how I can perform a double click.
Thanks
Always remember that protractor is a wrapper around webdriverjs.
doubleClick() is available in browser.actions():
browser.actions().doubleClick(element(by.id('mybutton'))).perform();
For anyone looking at this in 2019, this still works. Just know thatProtractor selectors use the Locator object to find elements. The above solution uses the webElement object. So if you're using Protractor to find your element, you'll need to do something like browser.actions().doubleClick(myElement.getWebElement()).perform();
var el=element(by.id('id'));
browser.executeAsyncScript(function() {
var evt=new MouseEvent('dblclick', {bubbles: true,cancelable: true,view: window});
var callback = arguments[arguments.length - 1];
arguments[0].addEventListener('dblclick',callback);
arguments[0].dispatchEvent(evt);
},el).then(function(){...});
await browser.actions().mouseMove(Element).doubleClick().perform();
await browser.actions().doubleClick(Element.getWebElement()).perform();
the above 2 codes works properly to double click on any element when it's visible on screen.
Here Element is
"let Element = element(by.xpath("locator"));"
Below code did not works as a msg is shown saying
"Failed: JavaScript error: arguments[0].dblclick is not a function"
whereas when checked in console similar scripts did worked to double click the item: "$($x(element(by.xpath("locator")))).dblclick()".
Will update my comment if able to find the exact JavaScript syntax to make below code run.
await browser.executeScript("arguments[0].dblclick();",
Element.getWebElement());

Categories