I am trying to get the anchorOffset of text selected by the user in A UIWebView. I have a short Javascript function (below) that is called when the user selects text and chooses an option from a custom contextual menu.
function textPosition()
{
var text = window.getSelection();
var x = text.anchorOffset;
return x;
}
I have a simple paragraph displayed in the UIWebView starting with:
This is a test sentence
Everything works as expected if I select a whole words... eg. if I select This the function returns 0, if I select sentence the function returns 15.
However if I move the handles on the selected text in the UIWebView the anchorOffset is different than expected. Eg. Selecting portions in the order as follows in the first word , this returns the following:
his returns 4
hi returns 1
Thi returns 3
Furthermore this is different depending on the order that I change the selection:
This returns 0
Thi returns 0
hi returns 3
It appears that the anchorOffset is different depending on from which end of the selection I alter the selection.
My questions are:
Am I making an obvious mistake?
Is this expected behaviour?
Is there something I can do to make the result consistent?
Thank you!
I now understand what I was doing wrong. It came from my misunderstanding of what an anchor actually is. I thought the anchorOffset referred to the the first part of a selection geographically but actually it relates to where the moused button was initially pressed (obviously not on a touch screen). The focusOffset relates to where the mouse button was released.
A nicer explanation can be found here:
mozilla developer site
With regard to a UIWebView an initial selection will place the anchor geographically at the start of the selected range and the focus at the end. However each time a selection handle is moved it becomes the focus and the other handle becomes the anchor.
Related
I can identify my currently focussed textbox with Window.selection:
var selection = window.getSelection();
I can identify the caret position with Selection.focusOffset:
var focus = selection.focusOffset;
Let's say that focus is currently 8, so the caret is 8 characters in.
How do I move the caret position, so it's e.g. 5 characters in?
Example method:
selection.setFocusOffset(5); // this method does not exist, so I need something similar
The Selection.extend() and Selection.modify() methods are able to move around the caret to some extend, but in my usecase where I manipulate and replace content inside the selection I need a more simple way to just determine how many characters in I want to place the caret. Btw: my textbox is a wysihtml textarea, which means that it's not technically a textarea div.
If I'm understanding correctly, you are wanting to change the start offset of focus, but Selection.extend() is only used to change the end offset. Since Selection.modify() is not on any standards track, there will not be a "simple way".
You will need to use Selection.getRangeAt() which returns a range object. Use the range objects API to set the start offset of your returned range, then use Selection.addRange() to make the new selection. You may want/need to removeRange() to clear the previous selection. I don't know how the browsers would handle overlapping selections.
I am using some JQuery Combobox that you can check out here: https://simpletutorials.com/uploads/1860/demo/index.html
As you can see, you can start typing and get the results filtered.
However, once you have selected a value, when clicking on the arrow to open the list, no other values are shown anymore. So, if I want to change college/state, I need to manually clear the input value. I don't like this, so I want to modify it.
I changed that code and added this JS on the click event of the list:
onclick="document.getElementById('statesCombo-ddi').value='';"
This line basically finds the input by id and sets its value to an empty string.
You can try out by looking for the td element having class "stc-button" (with Chrome, just focus on the arrow of the second combo box) and add my code to the tag.
===EDIT===
You can obtain the same results by adding this code directly to the input:
onclick="this.value=''"
===END EDIT===
This has a weird behavior:
If I SELECT an element from the list, it clears the value and everything works correctly.
If I TYPE some letters and then select a value from the list, no item is shown in the list after clicking.
What's wrong with it?
You can override one of the combo box methods to accomplish this:
STComboBox.prototype.filterAndResetSelected = function() {
this.$('ddi').val('');
this.filterList('');
this.selectRow(0);
this.$('ddl').scrollTop(0);
};
Does this help?
The unminified code is provided, is relatively small (12kb) and is fairly well commented, so you could make this modification directly to the source if you'd like.
Edit: Fixed to clear the input value (as indicated in the comment below)
By reading the source and doing a little debugging with Chrome's inspector (Control+Shift+i), you can find the particular ID of the element you need to clear (#collegesCombo-ddi) in order to clear the input box. Once you've found the element's ID you need to clear (and being very careful with plugins that assign multiple elements with the same ID, which is not allowed in the standard, and an indicator of poorly-written code):
$('#collegesCombo-ddi').val('');
I have been doing research on this simple sounding issue for a couple of days and I have not seen any result.
In a nutshell my problem is as follows: I would like to select text in a some input field, move focus to another field (or generally speaking some other element), but not lose my selected text.
Such a situation could correspond to a use-case in which I select text in a field, right-click and display a custom popup menu, but do not wish to lose focus of selected text, because I want to do some operations on the previously selected text.
A small code test sample would be (for my initial simple scenario - here I am forcing text selection when the second input field gains focus):
<html>
<head>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<input type="text" id="text1" size="20" value="Test1"/>
<input type="text" id="text2" size="20" value="Test2"/>
<script>
$('#text2').focus( function (evt) {
var target = $('#text1')[0];
target.select();
console.log('active/focused element: ' + document.activeElement.id);
});
</script>
</body>
</html>
I have been searching SO and web for a solution to this and have not seen much if any help.
I am not sure this is even really possible (due to the link between blur and selection lost and focus and selection). I have seen a style property called preventDeselect, in another SO answer - this does not work and I have not even such documentation or browser support for this.
I am quite struggling with this and would appreciate some help: even saying I can't do this at all or maybe some ways to go.
UPDATE:
Just for the record, my user scenario, which refers to text selection and context menu, is a common one (it slipped my mind to mention): just select some text in this page (or in an input type field) and right click to get the browser's default context menu - my scenario is different in that i want to use a custom menu, but with similar behavior to the browser's context menu - which normally allows to select some text, cut/copy the selection, navigate within the context menu without losing the selected text. So I think it should be possible somehow :) to do all these things with a context menu and still have your selection.
Attempting to answer this part of your question:
Such a situation could correspond to a use-case in which I select text
in a field, right-click and display a custom popup menu, but do not
wish to lose focus of selected text, because I want to do some
operations on the previously selected text.
For this use-case, I created a quick fiddle: http://jsfiddle.net/4XE9a/1/
Note: Am using the same getSelection function from #David's answer.
If you select any text and then right-click on the input, a custom popup menu appears. Click "option 1". You will find that the selection is not lost even though the focus has shifted to that anchor tag.
However, for the second part of your question regarding focus shifting to another textbox, #David's answer suffices.
Update: (after your comments)
Please see this updated fiddle: http://jsfiddle.net/783mA/1/
Now, when you select some text and right-click on the input it will show the custom popup menu with three options. Use tab to navigate and press space or click on the highlighted option. (Due to paucity of time I could not implement up/down arrow keys, but the concept remains the same)
This demonstrates your question in the comment that the selection is still not lost while navigating the menu.
Note: You are wanting to visually keep the selection highlight and not lose the selection while clicking anywhere else. Please note that this is not possible because text selection behavior is OS implemented. Browser, html etc do not play a role here. The text selection is lost as soon as you click anywhere outside the context of selection. This is because the system starts expecting a new selection as soon as you click anywhere outside. However, controls without text surface are exempt. Button, scrollbar arrows etc will not cause selection to lose.
To view this behaviour, in the fiddle, select some text and then click any dropdown on the left pane. The text selection is not lost, even visually for that matter.
This is why in the new fiddle above, I purposely used buttons to demonstrate.
You can save each selection in an interval, then retrieve it when you like. Here is an example that pulls the selection when the input has focus and clears the interval on blur:
function getSelection(elm) {
var start = elm.selectionStart;
var end = elm.selectionEnd;
return elm.value.substring(start, end);
}
$('input').focus(function() {
var self = this;
$(this).data('interval', setInterval(function() {
$(self).data('selection', getSelection(self));
},20));
}).blur(function() {
clearInterval($(this).data('interval'));
});
Now you can stuff like:
$('#text2').focus(function() {
console.log('selection in #text1 was: '+$('#text1').data('selection'));
});
Demo: http://jsfiddle.net/qCCY5/
I have a textbox and a set of buttons below the text box. What is suppose to happen is that a user fills in a number in the text box and that number determines how many buttons can be clicked. E.g if the text box has a value of 2, then the user can only select two button, a button is selected if the button turns red, it is not selected if it turns or stays white.
The problem is what is happening is that if the value is 1 or above, the user can select all the buttons, in other words if they just keep clicking on buttons then all the buttons would turn red, when what should happen is if the user goes over the value, then an error message appears stating you have went over the limit, please deselect a button if you want to choose another button.
How can I get it so that the number of buttons selected matches the value from the textbox?
code is in jsfiddle, click here (for some strange reason it is not letting me click on any button and text box is allowing entry of letters in jsfiddle, even though in my app with the exact code it works fine. Please look at function btnclick (btn) to help you.)
You're resetting the total on each click, so you're not really counting. Move the currenttotal = 0; outside the click function (and declare it with var).
Secondly, you have really much of the same code. You could also iterate to make the .className assignments on the buttons a bit more concise:
for(var i = 65; i <= 90; i++) { // iterate over character codes for A to Z
var letter = String.fromCharCode(i);
document.getElementById("answer" + letter).className = "answerBtnsOff";
}
You could also put the class names in HTML with the class="answerBtnsOff" attribute. You could even create the buttons through JavaScript. That would make for some cleaner and more readable code, but of course these optimizations are not necessary.
http://jsfiddle.net/7WwaK/3/
(For the jsFiddle to work, you have to select no wrap (body) in the left panel, but that's just how jsFiddle inserts the JavaScript.)
If I'm getting you right, you should do (IMHO) the following this:
Move var currenttotal = 0; outside your function. You are resetting it on each click on a button.
Edit the currenttotal after the user changes the number of answers. Add therefore the line currenttotal = document.getElementById('numberAnswerTxt').value(); to the function called getButtons().
You could implement the loop that pimvdb suggested to reduce your code (=
Please tell me if this is working.
I have a Dropdownlist or maybe better described as a "select" control. This list can have 50 to 100 items in it. Lets just say it's showing numerically 1 through 50.
I would like the control to show on the form with no selected value, however when the user clicks/focuses on it - I would like to have what appears to the user as the expanded list showing on items 20-40, with say item 30 being selected or highlighted.
Right now I have tried it with a focus event, and setting the selected value - however I have to set the selected value about 9-10 past what I actually want centered in the list.
Also, if the user ends up clicking outside of the box accidently I will end up capturing the default value I set.
Any ideas?
Thank you.
This is not doable with the generic <select> tag, and seems painfully nitpicky. You might want to consider either (a) not caring, or (b) using Javascript to create your own dropdown control.