I have lines of text generated by ng-repeat, displayed within a div. I would like the user to be able to select from those lines and press a button, and have the application know which lines the user selected
Is there any way to do that in AngularJS
In order to capture selected text in a browser, try the Rangy library. I have created a small example of how to use it. I'm sure you can expand it to match your needs.
If you need to take action immediately after user select the text (without button), you should listen for mouseup event. The following directive should help:
angular.module('myModule').directive('watchSelection', function() {
return {
link: function(scope, element) {
element.on('mouseup', function(event) {
var selection = rangy.getSelection();
// do something with selected text
});
}
};
});
You may also find this answer interesting.
Related
The coder's fantasy
I created a simple user script to act very quickly on the text I selected. It goes like this:
I select a word, a website (doesn't have to be a link), or a phrase from, let's say, a p element
When I press the trigger key, the algorithm will try to figure out if it's a website or text. It will open a tab: if it's a website, that's what it'll load; if it's text, it will google it.
The problem shows its ugly head
It works great except when I'm editing text. If I'm editing something I've written in a textarea/input it will fire, potentially losing what I wrote. Fortunately, there's usually cache, or even the site will warn me for having unsaved changes, which saves me from losing whatever I wrote. But it's something to fix.
The challenge
The userscript should only run on text that can't be edited. You'd think it is as easy as not calling the function if the selected text is within a textarea. But there are many ways to display editable content without using classical elements. The "best" filter I've found is to check for document.activeElement.isContentEditable. However, in this very box, that returns false. This is a textarea element, so I can add it to the filter, and I can do so with a few more I can think of. But apart from being an ugly solution, it is not foolproof.
Besides adding a "did you run me by accident?" prompt, is there a better way to do this?
Edit: my current code
If I understand correctly .... here is an example of how to go about it.
if (['TEXTAREA', 'INPUT'].includes(document.activeElement.nodeName)) {
// it is in textarea, input
}
else if (document.activeElement.isContentEditable) {
// it is in contentEditable element
}
else {
// not above
}
Above is not the only method, e.g. the following using window.getSelection():
const sel = window.getSelection();
const text = sel.toString();
if (!text.trim()) {
// there is no selection
// or selection is white-space
// or selection is in textarea, input
}
else if (document.activeElement.isContentEditable) {
// it is in contentEditable element
}
else {
// not above
}
I have a textarea and everytime a 'keyup' is detected it sets the current value of the textarea to the textareas text. Reason is, so that this text becomes a part of the HTML and I can then use localStorage to save the inputted text.
my code so far...
$(document).on('keyup', '.note_text', function () {
var text = $(this).val();
$(this).text(text);
});
My issue is, as soon as the keyup is detected the text area is no longer in focus so you have to click back into it and type again, and obviously you can only hold keys down to continuously type, as if you type normally the function is triggered by the key up.
I'm using $(document) as the textarea is dynamically created into the DOM
Add this, as explained in the jQuery documentation:
$("textarea").trigger("focus");
Which would be the same as the following without jQuery:
document.querySelector('textarea').focus();
Both of these examples are assuming that your html only contains one textarea. Otherwise you'd have to add logic to select the correct one.
After trial and error, I managed to find a working solution...
$(document).on('keyup', '.className', function () {
var text = $(this).val(); // Gets the text of the textarea being typed in
$(this).html(text); // Set the text as part of the html of the textarea
$(this).focus(); // refocuses back on the text area so the user can type
save(); // saves the DOM to the localStorage
});
I'm trying to customize the datatables search box in order to better integrate it into a bootstrap based UI. I have a table-controlbar 'horicontal_group' that contains other controls where I'd like to put the search box. It works as far as I can generate filtering events, however there is one very annoying problem:
the search box is loosing focus, every time the filter function is called.
This is a stopgap since I'd like typeahead functionality instead of letting the user click a button to search. I'd also implement a delay between keypresses and filter events of course, but first I have to deal with this focus issue.
This is how the dom looks like using the default 'f' option in datatable's sDom:
This is what I'd like to have:
wrapper_div.find('.dataTables_filter input')
.addClass('form-control tableview-search')
.appendTo(horicontal_group) //if this is uncommented, it works fine
.bind('keypress keyup', function(e){
datatable.fnFilter(searchTerm);
});
What I've tried so far (without any effect on the outcome):
use a freshly created input field instead of the field provided by the sDom-parameter 'f' (and delete 'f' from sDom)
use stopPropagation() on the event
unbind the events on the input field before binding the new ones
use .on('input' ..) instead of .bind('keypress keyup' ..)
append the whole dataTables_filter div to horicontal_group instead of just the input field
Ok, while writing this I've thought about it some more and I came to a solution that I'm gonna leave here. Using the built-in wrapper-div and adapting it to bootstrap instead of recreating it from scratch, solved my issues. If you have more insight on why the focus is lost I'd still be glad for your input.
I now initialize the sDom like this:
sDom: '<"row"<"col-lg-12 col-tableview-controls"f>><"row"<"col-lg-12"RlrtiS>>'
After dt is initialized I fixup the dom like this (note that I also used the merged search box from this thread: Add Bootstrap Glyphicon to Input Box:
var horicontal_group = wrapper_div.find('.dataTables_filter');
horicontal_group.addClass('input-group pull-right horicontal-group');
var merged_input = $("<div class='input-group merged'><span class='input-group-addon search-addon glyphicon glyphicon-search'></span></div>")
.appendTo(horicontal_group);
var input = horicontal_group.find('input');
input.addClass('form-control tableview-search')
.appendTo(merged_input)
.on("focus blur", function() {
$(this).prev().toggleClass("focusedInput")
});
var label = horicontal_group.find('label');
label.remove();
I have been working on the last bit of my php + ajax based datagrid project.Everything works as I designed except one thing : I cannot stop user opening multiple selection boxes...
Go my research page and use username "ChenxiMao" and password "accedo" to login(without double quotes).
Note that perhaps the images used in this datagrid would not be displayed when page is loaded for the first time(weird, I am trying to fix this, browser incompatibilities, perhaps).
If you double click on one cell in the "CONSULTANT" column, a html select box would be displayed, you can select one consultant to assign him to this task or unassign the consultant from this task. No problem for this.
The problem is : when user leaves this selection box OPEN, he/she can still open another selection box... My jquery code cannot stop people from opening multiple selection boxes.
You can ctrl-U to see the source code on this page, and check the content inside the "gridview-helper.js" for what I have been done.
I want to let user only open a single selection box. When he/she leaves the cell, the selection box should be closed, without changing the html inside...
Puzzled, screwed up for this afternoon...
Thanks for any suggestons in advance!
JavaScript is single-threaded, so you can add a mutex variable and check its value before opening a new select box.
At the top of gridview-helper.js:
var is_choice_visible = false;
In your double-click handler:
$(this).dblclick(function()
{
if (is_choice_visible)
return;
is_choice_visible = true;
...
For your select box, add an onblur handler which sets is_choice_visible back to false and deletes itself.
Unrelated tip: Growing a string in a loop is slow on older versions of Internet Explorer. It's more efficient to append to an array and join the array, e.g.:
var html = ["<select>..."];
for (var i in consultantnames)
{
html.push("<option>...</option>");
}
html.push("</select>");
return html.join("");
Have you tried using the onmouseout event on the cell, and removing the child dropdown box element if mouse out is triggered? Seems that should work.
I recall seeing a web site that when you highlighted/selected text on their page, it produced a small balloon just to the upper right, which was clickable and would perform some action when clicked. I have an application where this type of interface would be appropriate for my users. But... I haven't any idea what to call this widget nor where to start from scratch.
I think you may be referring to a tooltip. These are easily done with javascript; here are just a couple of options:
http://www.nickstakenburg.com/projects/prototip2/
http://craigsworks.com/projects/qtip/
You would use a javascript event to trigger the popup when the user selects some text. jQuery comes with some pre-rolled event handlers that will probably accomplish what you are looking for:
http://docs.jquery.com/Events/select
Noah
(Quick & Dirty) - Use this as a starting point. I'm going to assume that you're using jQuery to provide a cool tooltip to the user upon text selection, instead of the alert the code does. :p
function getSelection()
{
if(document.selection)
{
return document.selection.createRange().text;
}
else
{
return window.getSelection();
}
}
$(document).mouseup(function() { alert(getSelection()); });
This subscribes to the mouseup function and will alert whatever the user has selected, if anything. Naturally you'd have to flesh this out so that you check if the text is empty, and if not spawn a tooltip or do whatever you'd like with the text.