I have assembled a basic jfiddle below. For some reason my selector works to retrieve the textarea box to set the value, but the selector doesnt work to use the setSelectionRange function. On the console you'll find an error for .setSelectionRange is not a function.
http://jsfiddle.net/dMdHQ/6/
code(please refer to jfiddle):
selector.setSelectionRange(carat,carat);
setSelectionRange(carat,carat) is not a method on jquery object. You want to use it on DOM element. So try:
selector[0].setSelectionRange(carat,carat); //use `[0]` or .get(0) on the jquery object
See Reference
Fiddle
For me this is a good solution
selector[0].setSelectionRange(start ,end);
But I would like to add one more thing. I noticed that setSelectionRange is something that becomes available asynchronously after the element gets focus.
var element = selector[0];
element.addEventListener('focus', function() {
element.setSelectionRange(start, end);
});
element.focus();
Also you can use alternatively:
element.selectionStart = start;
element.selectionEnd = end;
HTML:
<input type="search" value="Potato Pancakes" id="search">
JQUERY:
jQuery.fn.putCursorAtEnd = function() {
return this.each(function() {
$(this).focus()
// If this function exists...
if (this.setSelectionRange) {
// ... then use it (Doesn't work in IE)
// Double the length because Opera is inconsistent about whether a carriage return is one character or two. Sigh.
var len = $(this).val().length * 2;
this.setSelectionRange(len, len);
} else {
// ... otherwise replace the contents with itself
// (Doesn't work in Google Chrome)
$(this).val($(this).val());
}
// Scroll to the bottom, in case we're in a tall textarea
// (Necessary for Firefox and Google Chrome)
this.scrollTop = 999999;
});
};
$("#search").putCursorAtEnd();
Check:
http://css-tricks.com/snippets/jquery/move-cursor-to-end-of-textarea-or-input/
You could try this which works for me. I use it to build an address from the separate address fields and then do the copy for pasting.
The HTML
<div id="d_clip_container" style="position:relative">
(copy to clipboard)
</div>;
<textarea id="clip" rows="0" cols="0" style="border:none;height:0;width:0;"></textarea>
The jQuery
$(document).ready(function() {
$('#d_clip_button').click(function() {
//get all the values of needed elements
var fName = $("#firstName").val();
var lName = $("#lastName").val();
var address = $("#Address").val();
var city = $("#City").val();
var state = $("#State").val();
var zip = $("#Zip").val();
//concatenate and set "clip" field with needed content
$('#clip').val(fName + " " + lName + "\n" + address + "\n" + city + ", " + state + " " + zip);
//Do it
if(copyToClipboard('#clip')) {
alert('text copied');
} else {
alert('copy failed');
}
});
});
function copyToClipboard(elem) {
// set focus to hidden element and select the content
$(elem).focus();
// select all the text therein
$(elem).select();
var succeed;
try {
succeed = document.execCommand("copy");
} catch(e) {
succeed = false;
}
// clear temporary content
$(target).val('');
return succeed;
}
Related
I tried searching, but am not finding a solution.
I am currently using Jquery autocomplete, along with an external service that stores the lists of possible returned results. The autocomplete is being done on a textarea, and I need to try to autocomplete for each line of text. So the user types one line, gets auto complete. Goes to a new line, starts typing, autocomplete appears only for what's on that line.
The set up is pretty standard to what JQuery shows off. I.E.:
<textarea id="entities"></textarea>
JS:
$("#entities").autocomplete({
serviceUrl: [the service url],
paramName: 'prefix'
});
I know there are ways to determine line number and get the value of a specific line such as:
$("#entities").on('keyup', function() {
var textLines = $("#entities").val().substr(0, $("#entities").selectionStart).split("\n");
var currentLineNumber = textLines.length - 1;
console.log(lines[currentLineNumber]);
});
But I'm not sure how I could call the autocomplete function upon typing a new line.
Edit: Someone suggested using contentEditable, but this results in different wrappers for each line depending on the browser.
<div id="entities" class="entities-text" contenteditable="true"></div>
IE converts each line to:
<p>Line 1</p>
<p>Line 2</p>
FF shows:
Line 1<br>
Line 2<br>
Chrome gives:
<div>Line 1</div>
<div>Line 2</div>
I am not so sure that you can achieve that so easily using a textarea and for each row of the textarea.
My suggestion is to switch to a contenteditable div, maybe formatted through CSS like a textarea if you want that style, then every time that you detect a new line, wrap the new line with an HTML element (for example a p).
Then just set the autocomplete to work with all the p elements inside that div.
Here you have a really good example on how to do that in case that you type a # (it's an autocomplete for email addresses).
Changing a bit the code, you will have your job pretty done.
autocomplete with contenteditable div instead of textarea doesn't seem to work
There is also a link to the jsfiddle example inside the post.
I think this Function help full to you ... complete your requirement.
function CreateTextAreaAutoFill(idstr, AutoFillAry) {
$("#" + idstr)
// don't navigate away from the field on tab when selecting an item
.on("keydown", function (event) {
if (event.keyCode === $.ui.keyCode.TAB &&
$(this).autocomplete("instance").menu.active) {
event.preventDefault();
}
})
.autocomplete({
minLength: 0,
source: function (request, response) {
// delegate back to autocomplete, but extract the last term
response($.ui.autocomplete.filter(
AutoFillAry, extractLast(request.term, idstr)));
},
focus: function () {
// prevent value inserted on focus
return false;
},
open: function (event, ui) {
// $(this).autocomplete('widget').find('li').css('font-size', '10px');
// $(this).autocomplete('widget').css('height', 100);
},
select: function (event, ui) {
//var terms = split(this.value);
//// remove the current input
//terms.pop();
//// add the selected item
//terms.push(ui.item.value);
//// add placeholder to get the comma-and-space at the end
//terms.push("");
//this.value = terms.join(" ");//terms.join(", ");
debugger;
var term = this.value;
var cursorPosition = $('#' + idstr).prop("selectionStart");
var SpaceInd = term.lastIndexOf(" ", (cursorPosition - 1));
// var SubStr = term.substring((SpaceInd + 1), cursorPosition);
var NewLineInd = term.lastIndexOf("\n", (cursorPosition - 1));
var SubStrInd = SpaceInd < NewLineInd ? NewLineInd : SpaceInd;
var FirstStr = this.value.substring(0, (SubStrInd + 1)) + ui.item.value;
this.value = FirstStr + this.value.substring(cursorPosition, this.value.length);
$('#' + idstr).prop('selectionEnd', FirstStr.length);
return false;
}
});
//function split(val) {
// // return val.split(/;\s*/);
// // return val.split(' ');
// var LineAry = val.split("\n");
// var FinalResult = [];
// $.each(LineAry, function (ind, Aval) {
// FinalResult = FinalResult.concat(Aval.split(' '));
// })
// return FinalResult;
//}
function extractLast(term, idstr) {
debugger;
var cursorPosition = $('#' + idstr).prop("selectionStart");
var SpaceInd = term.lastIndexOf(" ", (cursorPosition - 1));
var NewLineInd = term.lastIndexOf("\n", (cursorPosition - 1));
var SubStrInd = SpaceInd < NewLineInd ? NewLineInd : SpaceInd;
var SubStr = term.substring((SubStrInd + 1), cursorPosition);
return SubStr;//split(term).pop();
}
}
I've written a custom form validation script, but for some reason, wrapping input[type=text] elements in <div class="inputWrapper" /> stops me from preventing input[type=submit]'s default setting.
Here's the relevant code:
$("input[type=text]").wrap("<div class=\"inputWrapper\" />");
Is breaking:
$("input[type=submit]").click(function(event) {
event.preventDefault();
});
Why is this happening? If you need a more full script, let me know, and I'll just post the whole thing.
Alright, so for some reason, disabling that line of code allows .preventDefault on the input[type=submit] to work, but if I just use
// wrap inputs
$("input[type=text]").wrap("<div class=\"inputWrapper\" />");
// validate on form submit
$("input[type=submit]").click(function(event) {
event.preventDefault();
});
It works fine. So here's the full script, what could cause this weirdness?
$(document).ready(function() {
// wrap inputs
$("input[type=text]").wrap("<div class=\"inputWrapper\" />");
$("textarea").wrap("<div class=\"inputWrapper\" />");
// validate text inputs on un-focus
$("input[type=text].required").blur(function() {
if ($(this).hasClass("error")) {
// do nothing
} else if ($(this).val() === "") {
$(this).addClass("error");
$(this).parent(".inputWrapper").append("<div class=\"errorPopup\">" + $(this).attr("placeholder") + "</div>");
}
});
// validate textareas on un-focus
$("textarea.required").blur(function() {
if ($(this).hasClass("error")) {
// do nothing
} else if ($(this).val() === "") {
$(this).addClass("error");
$(this).parent(".inputWrapper").append("<div class=\"errorPopup\">" + $(this).attr("placeholder") + "</div>");
}
});
// validate on form submit
$("input[type=submit]").click(function(event) {
event.preventDefault();
// check fields
$(this).parent("form").children("input.required").each(function() {
// check textboxes
if ($(this + "[type=text]")) {
if (!$(this).val()) {
$(this).addClass("error");
};
};
// end textboxes
// check textareas
$(this).parent("form").children("textarea.required").each(function() {
if (!$(this).val()) {
$(this).addClass("error");
};
});
// end textareas
// check checkboxes and radio buttons
if ($(this).is(":checkbox") || $(this).is(":radio")) {
var inputName = $(this).attr("name");
if (!$("input[name=" + inputName + "]").is(":checked")) {
var inputId = $(this).attr("id");
$("label[for=" + inputId + "]").addClass("error");
};
};
// end checkboxes and radio buttons
});
// end fields
// submit form
var errorCheck = $(this).parent("form").children(".error").length > 0;
if (errorCheck == 0) {
$(this).parent("form").submit();
} else {
alert("You didn't fill out one or more fields. Please review the form.");
window.location = "#top";
};
// end submit form
});
// clear errors
$("input.required").each(function() {
// clear textboxes
if ($(this + "[type=text]")) {
$(this).keypress(function() {
$(this).removeClass("error");
$(this).next(".errorPopup").remove();
});
};
// end textboxes
// clear textareas
$("textarea.required").each(function() {
$(this).keypress(function() {
$(this).removeClass("error");
$(this).next(".errorPopup").remove();
});
});
// end textareas
// check checkboxes and radio buttons
if ($(this).is(":checkbox") || $(this).is(":radio")) {
var inputName = $(this).attr("name");
var labelFor = $(this).attr("id");
$(this).click(function() {
$("input[name=" + inputName + "]").each(function() {
var labelFor = $(this).attr("id");
$("label[for=" + labelFor + "]").removeClass("error");
});
});
};
// end checkboxes and radio buttons
});
// end clear textbox errors
});
Alright, I was wrong about what the problem was. It's related to the line I thought it was, but it's actually having an issue finding the .error after I wrap the inputs.
Here's where the problem lies:
var errorCheck = $(this).parent("form").children(".error").length > 0;`\
var errorCheck = $(this).parent("form").children(".error").length > 0;
When you .wrap the text inputs, they are no longer children of the form. Use .find
By the way, $(this + "selector") is not valid. You probably want to use $(this).is("selector")
You will need some sort of reference maintained with the new DOM element. This would be placing it as an initialised DOM element in a variable first (not as a string as you did) and the same for the original element, which will be placed back in to maintain the event:
var $inputWrapper = $("<div class=\"inputWrapper\" />"),
$inputText = $("input[type=text]");
$inputText.wrap("<div class=\"inputWrapper\" />");
Then you can replace the element back in.
I'm making a kind of text editor in a textarea where I process user input, including tabs. Every time the user inputs something, I run a paginate() function which paginates the text correctly on the page, this function takes about 20 milliseconds. Now, because I don't want a second input to be processed while the textarea is being paginated I've added a condition but that way I'm losing ctrl-V</kbdI functionality. So, following a suggestion by #Gabriel Gartz at this post: textarea on input issue.
I call again the function by saving first the context and the event. The function does get called again, but the paste still doesn't take place!
html:
<textarea id="taEditor"></textarea>
Javascript:
$("#taEditor").on('click keydown cut paste', processUserInput);
var IsProcessingEvent = false;
function processUserInput(e) {
if(!IsProcessingEvent) {
IsProcessingEvent = true;
//do various stuff before the textarea changes like: get value, get cursor pos etc
var taValueBefore = document.getElementById("taEditor").value;
if (e.keyCode === 9) {
e.preventDefault();
e.stopPropagation();
document.getElementById("taEditor").value += "\t";
}
getcursorpos();
//do various stuff after the textarea changes like: get value, get cursor pos etc
setTimeout(function() {
var taValueAfter = document.getElementById("taEditor").value;
getcursorpos();
if (taValueAfter !== taValueBefore) {
paginate(); //this function paginates the text in the textarea and sets the cursor
//paginate() takes about 20 milliseconds
}
if (doAgain.repeat) {
var lastEvent = doAgain;
doAgain.repeat = false;
document.getElementById("debug").innerHTML += "rerun: " + lastEvent.ctx.id + ":" + lastEvent.e.type + "<br>";
setTimeout(processUserInput.bind(lastEvent.ctx), 0, lastEvent.e);
}
document.getElementById("debug").innerHTML += e.type + "<br>";
IsProcessingEvent = false;
}, 0);
} else {
//save context and event
document.getElementById("debug").innerHTML += "isprocessing: " + e.type + "<br>";
doAgain = {
ctx: this,
e: e,
repeat: true
};
//i need to preventdefault here, because processUerInput also processes the TAB key and if i don't use preventdefault then the cursor will move focus to other elements during the pagination
e.preventDefault();
e.stopPropagation();
return false;
}
}
var doAgain = {
ctx: "",
e: "",
repeat: false
};
function getcursorpos() {
//for simplicity reasons it's empty
}
function paginate() {
var i = 0;
var k = 0;
//simulate 20-30 milliseconds of delay for pagination
for (i=0;i<100000000;i++) {
k++;
}
//for simplicity reasons it's empty
}
jsfiddle:
http://jsfiddle.net/63pkE/1/
to reproduce the problem: try to ctrl-v in the textarea.
I don't understand what I'm doing wrong.
EDIT
Here is a new jsfiddle where I replaced the
setTimeout(processUserInput.bind(lastEvent.ctx), 0, lastEvent.e);
line with
setTimeout(function() {
processUserInput.call(lastEvent.ctx, lastEvent.e);
}, 0);
since .bind is not crossbrowser and still it DOESN'T work.
http://jsfiddle.net/63pkE/2/
Try this and see if if works, I didn't notice any difference from your original code behavior and copy paste work now.
function processUserInput(e) {
if(!IsProcessingEvent) {
if(!e.ctrlKey){
IsProcessingEvent = true;
}
//Rest of the code
e.ctrlKey returns true if the Ctrl key is pressed.
I have this scenario, I am detecting all forms on a site: document.forms
And I am trying to detect which forms are visible and which are not visible.
var formElement = []
for (i=0,l=document.forms.length;i<l;i++){
var formIndex = document.forms.item(i);
if (<need here just visible forms>){
formElement.push(formIndex);
}
}
Just to say I am doing this over an other pop up window that is communicating with the browser window with that forms, this depends on jQuery being present on the host site so jQuery is not a solution.
What is the best way to do this.
var isVisible = form.style.display != 'none';
UPDATE #1: hidden attribute
Also the element can be invisible if hidden attribute is specified, so the condition
could be changed to
var isVisible = form.style.display != 'none' && !form.hasAttribute('hidden');
UPDATE #2: jQuery approach:
Find all invisible forms:
$('form:hidden');
or
$('form:not(:visible)');
Find all visible forms:
$('form:visible');
Check is form visible:
$(form).is(':visible');
UPDATE #3: particular case (for original code in question)
It's working pretty well to determine visible forms using a function from my demo:
function isVisible(el) {
return el.style.display != 'none' && !el.hidden;
}
var formElement = [];
for (i=0, l=document.forms.length; i<l; i++) {
var formIndex = document.forms.item(i);
if(isVisible(formIndex)) {
formElement.push(formIndex);
}
}
console.log(formElement);
It's the same loop is this one in demo:
for(var i = document.forms.length; 0 < i--;) {
log('Form #' + i + ': ' + isVisible(document.forms[i]));
}
DEMO
UPDATE #4: pop-up window
I've adapted my example for pop-up window, but I have to say that you're NOT ABLE to deal with elements in document from other host - both pop-up and opener windows should belong to same host.
<script type="text/javascript">
var wnd = window.open('popup.html');
function isVisible(el) {
return el.style.display != 'none' && !el.hidden;
}
wnd.onload = function() {
/* This is working pretty well: */
var formElement = [];
console.log(wnd.document.forms);
for (i=0,l=wnd.document.forms.length;i<l;i++){
var formIndex = wnd.document.forms.item(i);
console.log(formIndex);
if (isVisible(formIndex)){
formElement.push(formIndex);
console.log('Form ' + formIndex.id + ' is visible');
}
}
};
</script>
var forms = document.getElementsByTagName("form");
Then, you can loop through the array and check to see if the tag is visible or not.
You can use this:
$(element).is(":visible") // Checks for display:[none|block], ignores visible:[true|false]
Ref. How do I check if an element is hidden in jQuery?
you can use :
$('#form').is(':visible')
The following will go through all forms and tell which ones are visible and which aren't:
$("form").each(function() {
if ($(this).is(":visible")) {
console.log("Visible: ", this);
} else {
console.log("Hidden: ", this);
}
});
or if you want to get all visible ones at once:
$("form:visible")
And the hidden ones:
$("form:hidden")
I understand that with javascript you can select the contents of a textbox with the following code (in jQuery):
$("#txt1").select();
Is there a way to do the opposite? To deselect the content of a textbox? I have the focus event of a series of textboxes set to select the contents within them. There are times now that I want to focus a particular textbox WITHOUT selecting it. What I am planning on doing is calling the focus event for this particular textbox, but then follow it with a call to deselect it.
$("input[type=text]").focus(function() {
$(this).select();
});
//code....
$("#txt1").focus();
//some code here to deselect the contents of this textbox
Any ideas?
Thanks!
what about this:
$("input").focus(function(){
this.selectionStart = this.selectionEnd = -1;
});
If you just assign the value of the textbox to itself, it should deselect the text.
You need to set the selectionStart and selectionEnd attribute. But for some reason, setting these on focus event doesn't work (I have no idea why). To make it work, set the attributes after a small interval.
$(document).ready(function(){
$('#txt1').focus(function(){
setTimeout(function(){
// set selection start, end to 0
$('#txt1').attr('selectionStart',0);
$('#txt1').attr('selectionEnd',0);
},50); // call the function after 50ms
});
});
To "focus a particular textbox WITHOUT selecting it":
I would use the part of the patched jquery plugin jquery-fieldselection
using that you can call
$('#my_text_input').setSelection({"start":0, "end":0}); // leaves the cursor at the left
or use this reduced version that places the cursor at the end of the text (by default)
(function() {
var fieldSelection = {
setSelection: function() {
var e = (this.jquery) ? this[0] : this, len = this.val().length || ;
var args = arguments[0] || {"start":len, "end":len};
/* mozilla / dom 3.0 */
if ('selectionStart' in e) {
if (args.start != undefined) {
e.selectionStart = args.start;
}
if (args.end != undefined) {
e.selectionEnd = args.end;
}
e.focus();
}
/* exploder */
else if (document.selection) {
e.focus();
var range = document.selection.createRange();
if (args.start != undefined) {
range.moveStart('character', args.start);
range.collapse();
}
if (args.end != undefined) {
range.moveEnd('character', args.end);
}
range.select();
}
return this;
}
};
jQuery.each(fieldSelection, function(i) { jQuery.fn[i] = this; });
})();
used this way:
$('#my_text_input').setSelection(); // leaves the cursor at the right
Rather than selecting and then deselecting, why not just temporarily store a boolean on the dom element?
$("input[type=text]").focus(function() {
if($(this).skipFocus) return;
$(this).select();
});
//code....
$("#txt1").skipFocus = true;
$("#txt1").focus();
I'd like to suggest a simple solution
$("input[type=text]").focus(function() {
$(this).select();
});
$("input[type=text]").blur(function() {
$('input[type="hidden"][value=""]').select();
});
//code....
$("#txt1").focus();
Here is a simple solution without jquery
<input type="text" onblur="this.selectionStart = this.selectionEnd = -1;">
If you want to deselect a text box using jQuery do the following:
$(your_input_selector).attr('disabled', 'disabled');
$(your_input_selector).removeAttr('disabled');