JS/jQuery > Highlight Text In Appended Imput - javascript

Upon clicking on my contextmenu menu (right-click custom menu), I have multiple cases set. The snippet below is the one set for renaming the folder (menu li > a value) which hides the link within the <li>...</li> and adds an input field.
$(document).ready(function() {
"use strict";
$(document).on('mousedown', function(e) {
if ($(e.target).parent().hasClass('custom-menu')) {
switch (action) {
case 'rename-folder':
anchor = clicked.find('a').first();
anchor.before($('<input />', {
type: 'text',
value: $(anchor).text(),
'class': 'FolderRenaming',
focusout: function() {
$(this).siblings('a').html($(this).val()).show();
$(this).remove();
$(anchor).parent().removeClass('clicked');
}
})).hide();
break;
}
}
}).on('keyup', 'input.rename', function(e) {
e.preventDefault();
if (e.keyCode === 13) {
$(e.target).focusout();
}
});
});
You right click and choose the option to 'rename'. You've then got to click within this input field and either hit enter or outside of the field for the reverse to take place.
How can I make it so upon clicking to rename, the text within the appended <input> is highlighted and therefore focused in?

You can use the jQuery focus() function on an element to achieve this.
By changing your before() call, to an insertBefore() call, you can chain the focus() method onto the element you are appending.
case 'rename-folder':
anchor = clicked.find('a').first().hide();
$('<input />', {
type: 'text',
value: $(anchor).text(),
'class': 'FolderRenaming',
focusout: function() {
$(this).siblings('a').html($(this).val()).show();
$(this).remove();
$(anchor).parent().removeClass('clicked');
}
}).insertBefore(anchor).focus();
break;
I haven't tested the above, as your code was just a snippet, but have created a basic implementation of the above here:
https://jsfiddle.net/michaelvinall/w6q09rzs/1/

Related

this.id on an Element Event Listener becomes an array of all id's of elements clicked

I have an event listener on all textboxes. When a textbox is clicked, I'd like to open a keyboard. On Enter of the keyboard I'd then like to use the id of the textbox which called it to do some logic. However the id (txtbxId in code) just becomes the first textbox I click, then the second textbox I click in an array.
E.g, the alert becomes 'textbox1' - after second textbox click alert is 'textbox1' 'textbox2'
I've tried to force the variable id to '', to delete it etc. to no avail,
Code snippet here:
$('.textbox').click(function() {
var txtbxId = this.id;
$("#Keyboard").show();
$(document).on('keydown', function(e) {
if (e.which === 13) {
alert(txtbxId);
}
});
});
});
The issue is because you're nesting events. Therefore as well as duplicating the keydown event when a click event happens, you're supplying each individual id to those events.
To fix this, use a single event handler for all the .textbox elements, and read their own id from the reference to the element which raised the event which is available through the this keyword:
$('.textbox').click(function() {
$("#Keyboard").show();
});
$(document).on('keydown', '.textbox', function(e) {
if (e.which === 13) {
alert(this.id);
}
});
The problem is that your on('keydown') function the first time you click a textbox never gets unassigned, so for every time you click a .textbox, you're making a NEW keydown callback, but not removing your old ones.
I would recommend making an object outside of your onClick callback which manages .keydown callbacks, so that you only have one at any time.
Something like this:
window.keydownmanager = {
init: () => {
$(document).on('keydown', function (e) {
window.keydownmanager.callback(e);
});
},
callback: () => {},
setCallback: (cb) => {
window.keydownmanager.callback = cb;
}
}
And inside your onClick callback, do this:
var txtbxId = this.id;
$("#Keyboard").show();
window.keydownmanager.setCallback(function(e) {
if (e.which === 13) {
alert(txtbxId);
}
})

Deselect a radio option

I'm using the bootstrap radio buttons and would like to allow deselection of a radio group. This can be done using an extra button (Fiddle). Instead of an extra button, however, I would like to deselect a selected radio option if the option is clicked when it's active.
I have tried this
$(".btn-group label").on("click", function(e) {
var clickedLabel = $(this);
if ($(clickedLabel).hasClass("active"))
{
// an active option was clicked => deselect it
$(clickedLabel).children("input:radio").prop("checked", false)
$(clickedLabel).removeClass("active");
}
}
)
but there seems to be a race condition: the event of clicking the label that I use seems to be used by bootstrap.js to set the clicked label option to "active". If I introduce a timeout, the class "active" is removed successfully:
$(".btn-group label").on("click", function(e) {
var clickedLabel = $(this);
if ($(clickedLabel).hasClass("active"))
{
setTimeout(function() {
// an active option was clicked => deselect it
$(clickedLabel).children("input:radio").prop("checked", false)
$(clickedLabel).removeClass("active");
}, 500)
}
}
)
How can I toggle a selected option successfully without using a timeout?? Thank you for help.
Instead of using two method's preventDefault & stopPropagation, use return false, will work same.
The difference is that return false; takes things a bit further in
that it also prevents that event from propagating (or "bubbling up")
the DOM. The you-may-not-know-this bit is that whenever an event
happens on an element, that event is triggered on every single parent
element as well.
$(".btn-group label").on("click", function(e) {
var clickedLabel = $(this);
if ($(clickedLabel).hasClass("active"))
{
// an active option was clicked => deselect it
$(clickedLabel).children("input:radio").prop("checked", false)
$(clickedLabel).removeClass("active");
return false;
}
});
After messing with your code in jsfiddle for a while I figured out that a combination of preventDefault() and stopPropagation() does the trick.
Here's a fiddle
and the code:
$(".btn-group label").on("click", function(e) {
var clickedLabel = $(this);
if ($(clickedLabel).hasClass("active"))
{
// an active option was clicked => deselect it
$(clickedLabel).children("input:radio").prop("checked", false)
$(clickedLabel).removeClass("active");
e.preventDefault();
e.stopPropagation();
}
}
);

X-Editable: stop propagation on "click to edit"

I have an editable element inside a div which itself is clickable. Whenever I click the x-editable anchor element, the click bubbles up the DOM and triggers a click on the parent div. How can I prevent that? I know it's possible to stop this with jQuery's stopPropagation() but where would I call this method?
Here's the JSFiddle with the problem: http://jsfiddle.net/4RZvV/ . To replicate click on the editable values and you'll see that the containing div will catch a click event. This also happens when I click anywhere on the x-editable popup and I'd like to prevent that as well.
EDIT after lightswitch05 answer
I have multiple dynamic DIVs which should be selectable so I couldn't use a global variable. I added an attribute to the .editable-click anchors which get's changed instead.
editable-active is used to know if the popup is open or not
editable-activateable is used instead to know if that .editable-click anchor should be treated like it is
$(document).on('shown', "a.editable-click[editable-activateable]", function(e, reason) {
return $(this).attr("editable-active", true);
});
$(document).on('hidden', "a.editable-click[editable-activateable]", function(e, reason) {
return $(this).removeAttr("editable-active");
});
The check is pretty much like you've described it
$(document).on("click", ".version", function() {
$this = $(this)
// Check that the xeditable popup is not open
if($this.find("a[editable-active]").length === 0) { // means that editable popup is not open so we can do the stuff
// ... do stuff ...
}
})
For the click on the links, simply catch the click event and stop it:
$("a.editable-click").click(function(e){
e.stopPropagation();
});
The clicks within X-editable are a bit trickier. One way is to save a flag on weather the X-editable window is open or not, and only take action if X-editable is closed
var editableActive = false;
$("a.editable-click").on('shown', function(e, reason) {
editableActive = true;
});
$("a.editable-click").on('hidden', function(e, reason) {
editableActive = false;
});
$("div.version").click(function(e) {
var $this;
$this = $(this);
if(editableActive === false){
if ($this.hasClass("selected")) {
$(this).removeClass("selected");
} else {
$(this).addClass("selected");
}
}
});
Fixed Fiddle
It's not pretty, but we solved this problem with something like:
$('.some-class').click(function(event) {
if(event.target.tagName === "A" || event.target.tagName === "INPUT" || event.target.tagName === "BUTTON"){
return;
}
We're still looking for a solution that doesn't require a specific list of tagNames that are okay to click on.

Global click event blocks element's click event

This should happen
If the user clicks on one of the two input boxes, the default value should be removed. When the user clicks elswhere on the webpage and one text field is empty, it should be filled with the default value from the data-default attribute of the spefic element.
This happens
When somebody clicks somewhere on the page and the field is empty, the field will be filled with the right value, but when somebody clicks in the field again the text isn't removed. It seems like the $(document) click event is blocking the $(".login-input") click event, because the $(".login-input") is working without the $(document) click event.
JSFiddle
A sample of my problem is provieded here: JSFiddle
Tank you for helping!
When you click on the input, the script is working, but since the input is in the document, a click on the input is a click on the document aswell. Both function will rune, document is the last one.
That is called event bubblingand you need to stop propagation :
$(document).ready(function () {
$(".login-input").click(function (e) {
e.stopPropagation()
$(this).val("");
});
});
Fiddle : http://jsfiddle.net/kLQW9/3/
That's not at all how you solve placeholders, you do it like so :
$(document).ready(function () {
$(".login-input").on({
focus: function () {
if (this.value == $(this).data('default')) this.value = '';
},
blur: function() {
if (this.value == '') this.value = $(this).data('default');
}
});
});
FIDDLE
Preferably you'd use the HTML5 placeholder attribute if really old browsers aren't an issue.
EDIT:
if you decide to do both, check support for placeholders in the browser before applying the javascript :
var i = document.createElement('input'),
hasPlaceholders = 'placeholder' in i;
if (!hasPlaceholders) {
// place the code above here, the condition will
// fail if placeholders aren't supported
}
Try below code
$(document).ready(function () {
$(".login-input").click(function () {
$(this).val("");
});
});
$(document).ready(function () {
$(".login-input").each(function () {
if ($(this).val() === "") {
$(this).val($(this).attr("data-default"));
}
});
$(".login-input").blur(function () {
if ($(this).val() === "") {
$(this).val($(this).attr("data-default"));
}
});
});
Check fiddle
Why not to use focus and blur events?
$(document).ready(function () {
$(".login-input").focus(function () {
$(this).val("");
});
});
$(document).ready(function () {
$(".login-input").blur(function () {
if ($(this).val() === "") {
$(this).val($(this).attr("data-default"));
}
});
});
http://jsfiddle.net/kLQW9/5/
P.S. In yours, and this code, on focus all data fro input will be cleared. If you need to clear only default text, add proper condition for that.

OnBlur effect for select dropdown

I have a select dropdown and if a user clicks 'outside' of that select dropdown, I want it to disappear. This is what I currently have:
$(this).html($("<select/>", {
id: 'sel',
change: function() {
selectdone(this, title_id, status_type);
},
blur: function() {
selectdone(this, title_id, status_type);
},
In the above, if I click outside of the dropdown, nothing happens. The only time the function is firing is if I change the value of the select dropdown.
How would I accomplish the above, such that when a user clicks anywhere on the document outside of the select dropdown, it fires this function?
I don't think this is possible. As pointed out in another answer, it appears that the active <select> is prohibiting other input from being accepted.
See my updated fiddle. Notice that when you click the background you get the alert test when the select isn't expanded. When it is expanded and you click off, the alert doesn't fire. This appears to be the default behavior of the browser. It appears to be ignoring all other inputs (mouse movements included) while the select is activated.
I was, however, able to get your event to fire for any selected element by setting the selectedIndex to -1. This way any valid option will result in a change.
Example
$(function(){
var title_id = '', status_type = '';
$('body').html(
$("<select/>", {
id: 'sel',
change: function() {
selectdone(this, title_id, status_type);
},
blur: function() {
selectdone(this, title_id, status_type);
}
})
.append($('<option />', { 'text':'one'}))
.append($('<option />', { 'text':'two'}))
);
$('#sel').prop('selectedIndex', -1);
});
function selectdone(element, titleid, statustype){
$(element).hide().prop('selectedIndex', -1);
}

Categories

Resources