I have a web application which has an onchange event for loading multiple select options to a textbox separated by ',' and slice the last ','
It's working fine,
I have an another function for form filling. When I try to load the form only select option is being updated expecting onchange function to get data from select and have some value in textbox.
But sadly it's not working but working only after new option is selected or removed and added back
Function for adding multiple select data to textbox with onchange event:
// arguments: reference to select list, callback function (optional)
function getSelectedOptions(sel,fn) {
var opts = [], opt;
// loop through options in select list
for (var i=0, len=sel.options.length; i<len; i++) {
opt = sel.options[i];
// check if selected
if ( opt.selected ) {
// add to array of option elements to return from this function
opts.push(opt);
// invoke optional callback function if provided
if (fn) {
fn(opt);
}}}
// return array containing references to selected option elements
return opts;
}
// example callback function (selected options passed one by one)
function callback(opt) {
// display in textarea for this example
var display = document.getElementById('display');
display.innerHTML += opt.value + ',';
}
// anonymous function onchange for select list with id lstBox2
document.getElementById('sel1').onchange = function(e) {
// get reference to display textareaa
var display = document.getElementById('display');
display.innerHTML = ''; // reset
// callback fn handles selected options
getSelectedOptions(this, callback);
// remove ', ' at end of string
var str = display.innerHTML.slice(0, -1);
display.innerHTML = str;
};
Function to form filling:
$(document).ready(function () {
tests = split[testIndex];
// $('#display2').val(tests);
var opt2 = '<option selected>' + tests + '</option>';
$('#sel').append(opt2);})
Try moving your document.getElementById('sel1').onchange code into the $(document).ready(...) block. It's hard to tell without a complete page example, but one possibility is that 'sel1' isn't part of the DOM yet when you try to add the onchange handler.
Try to use
$('body').on('change', '#sel1', function(e) {
});
instead if the elements are added after load.
Related
I've got a table with a button inside a td, once I press the button it adds text to the td. I want to remove this text inside the td once i press the button again. note that this button is used multiple times in the table hence the class attribute.
Which method could I use to get this done?
This is my code:
$(document).on('click', '.releasebutton', function () { // button class="releasebutton"
var label = $(this).text();
if (label == "Add") { // it is "Add" by default
$(this).text("Cancel");
$('.ReleaseTD').append("<br>" + "test"); // td class="ReleaseTD"
}
// the code above this works
else {
$(this).text("Add");
$('.ReleaseTD').remove("<br>" + "test");
// this obviously is wrong but this is where i would like the correct code
};
});
You could create ID for text inside like this:
$(document).on('click', '.releasebutton', function () { // button class="releasebutton"
var label = $(this).text();
if (label == "Add") { // it is "Add" by default
$(this).text("Cancel");
$('.ReleaseTD').append("<span id='textID'><br>" + "test</span>");
}
else {
$(this).text("Add");
$('#textID').remove();
};
});
Please try the following:
$(document).on('click', '.releasebutton', function () { // button class="releasebutton"
var label = $(this).text();
if (label == "Add") { // it is "Add" by default
$(this).text("Cancel");
$('.ReleaseTD').append("<span id='txt_name'><br>" + "test</span>");
}
// the code above this works
else {
$(this).text("Add");
$('#txt_name').remove();
};
});
Two ways:
1) Append your text into a span with a unique ID, and then delete this ID. For example, delete the ID with the largest number. Dumbest way would be to just store the latest ID in a global variable.
var global_last_appended_id = 0;
$(document).on('click', '.releasebutton', function () { // button class="releasebutton"
global_last_appended_id ++;
$('.ReleaseTD').append("<span id='appended-text-" + global_last_appended_id + "'><br>" + "test</span>");
}
// the code above this works
else {
$(this).text("Add");
$('#appended-text-' + global_last_appended_id).remove();
global_last_appended_id--; //go one step back so next time we remove the previous paragraph
};
});
Update: after your edit I've added the ability to undo multiple times. Basically there is unlimited undo.
2) [lame and wrong] Save the previous .html() - the whole HTML code of your element - into a global variable; then restore the previous version of the text from the global variable when necessary.
I want to have an element visible only if another element's value is not empty.
Right now I'm doing this using:
function setReceiveSmsNotificationsCheckboxArea() {
var checkbox = $('#ReceiveSmsNotifications');
var value = !!$('#Cellphone').val().trim(); //bool depending on txt val
checkbox.prop('checked', value);
checkbox.closest('.form-group').toggle(value);
}
$('#Cellphone').change(function () {
setReceiveSmsNotificationsCheckboxArea();
});
$(document).ready(setReceiveSmsNotificationsCheckboxArea);
Is there a way to combine the two latter functions to one (so that the change even runs on startup as well?)
You can trigger the change event on page load in order to trigger the handler
function setReceiveSmsNotificationsCheckboxArea() {
var checkbox = $('#ReceiveSmsNotifications');
var value = !!$('#Cellphone').val().trim(); //bool depending on txt val
checkbox.prop('checked', value);
checkbox.closest('.form-group').toggle(value);
}
$('#Cellphone').change(setReceiveSmsNotificationsCheckboxArea).change();
I want to create DOM elements with info taken from input type text. To be more specific:
I want the user to be able to write a location and after he presses "Go!" button an element to be created with the text inserted and I also want to have a delete icon which when pressed to delete that insert.
I created a function in which I took the input value but I cannot create the 'del' button
If I create another <img> inside using the same method, when I create the second entry it will put another <img> to the previous entry
search_btn.click(function() {
var place_reg = /^[a-z]+\d*[a-z]*(\s[a-z]+\d*[a-z]*)*?$/i;
var search_value = search_box.val();
var final_result = search_value.trim();
if (place_reg.test(final_result)) {
createDest(final_result);
} else {
alert('Please insert a valid destination');
}
document.getElementById('search_box').value = "";
});
function toTitleCase(str) {
return str.replace(/\w\S*/g, function(txt){ return txt.charAt(0).toUpperCase() +
txt.substr(1).toLowerCase();});
}
function createDest(value) {
var destination_i_search = document.createElement("div");
destination_i_search.innerHTML = toTitleCase(value);
destination_i_search.setAttribute("class" , "place");
$("#dest").append(destination_i_search);
}
It is very difficult to understand what you wish it to do, without a full example, but from comments you may want something like this:
JSFiddle: http://jsfiddle.net/TrueBlueAussie/s6hn0n18/6/
I have converted it to use jQuery where appropriate.
var search_btn = $('#search');
var search_box = $('#searchbox');
search_btn.click(function () {
var place_reg = /^[a-z]+\d*[a-z]*(\s[a-z]+\d*[a-z]*)*?$/i;
var search_value = search_box.val() || "";
var final_result = search_value.trim();
if (place_reg.test(final_result)) {
createDest(final_result);
} else {
alert('Please insert a valid destination');
}
search_box.val("");
});
function toTitleCase(str) {
return str.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
}
function createDest(value) {
// use a div container
var div = $("<div/>");
div.html(toTitleCase(value));
div.addClass("place");
// If you want to replace the previous entry
$("#dest").append(div);
var del = $('<input class="delete" type="button" value="X"/>');
$("#dest").append(del);
}
// This is a delegated event handler, attached to a non-changing ancestor
$(document).on('click', '.delete', function(){
// Remove the previous div (if of class place)
$(this).prev('.place').remove();
// Remove the delete button too
$(this).remove();
});
The key is to add a delegated event handler for the delete buttons. These work by listening for the specified event (click in this case) bubbling up to a non-changing ancestor. It the applies the jQuery selector. It the calls the function for any matching element that caused the event. The default ancestor is document if nothing closer to the changing content is available. In this case you could use #dest
e.g.
$('#dest').on('click', '.delete', function(){
I have this problem trying to getting one single function attach multiple individual functions on "Change" event of a dropdown list using for ... in loop. The $('select') object top has no method 'on' is the Type error detected by Chrome Debugger.
Here is my code: (I don't have much JavaScript / jQuery knowledge so please be bear up with my coding)
function AKaizerDropdown(HiddenFeild) { //#id of hidden field passed as parameter
var select = $('select'); // select object assigned to variable
var selectcount = 0;
var Selecthold=new Array();
for (select in this) {
select.on('change', function() {
var SelectedIndex = this.attr('selectedIndex');
selecthold[selectcount] = [select.attr('id'), selectedindex];
//Select ID and Selected index assigned as an array into Selecthold Array element
});
selectcount +=1;
}
var item= new array();
//Elements in selecthold array printed onto hidden field
for (item in selecthold) {
$(HiddenFeild).val += item[0] + item[1]; //Assigns values to element Hiddenfield in DOM
}
}
Edited Code :
$.fn.AKaizerDropdown = function (HiddenFeild) {
var select_ = $(this).find('select');
var selectcount = 0;
var Selecthold=new Array();
select_.each(function () {
$(this).on('change', function () { //everything runs fine except dropdownlist doesn't enter into this event when an item is chosen
var SelectedIndex = this.selectedIndex;
Selecthold[selectcount] = [this.id, Selectedindex];
});
});
var button_ = $(this).find('input')
button_.on('click', function () {
for (item in Selecthold) {
$(HiddenFeild).val += item[0] + item[1]+','; //Assigns values to element Hiddenfeild in DOM seperated by ","
}
});
}
Somewhat fixed code still doesn't work
Here is the part where i attach it to popover Bootstrap(twitter 2.3.2) .
//think the problem lies here where the pop up seems to re-render the same same html found in ($#KaizerDragon") where all JavaScript is probably discarded?
$("#ContentPlaceHolder1_ADragonTreeviewt41").popover({
html: true, container: 'body',
trigger: 'click',
content: function () {
$(function () {
$("#KaizerDragon").AKaizerDropdown();
});
return $("#KaizerDragon").html();
}
});
So my question is how can I correct the above code to get the intended output(as in comments within code) ?
You are declaring
var select = $('select'); // select object assigned to variable
But then overriding the value in your for loop
for (select in this) ...
That is to say, the select inside the loop isn't the same as you declared above.
try something like this
select.each(function(){
$(this).on('change', function() {
var SelectedIndex = this.selectedIndex;
Selecthold[selectcount] = [this.id, SelectedIndex];
//Select ID and Selected index assigned as an array into Selecthold Array element
});
})
I have the following Javascript that on a single mouse click in a table cell with id="freq-table" populates consecutive <input> form fields with id="searchTerm(x)" with the cell's value. It's referenced in the <body> tag as:
<body onload="populateFields()>
and <table> tag as:
<table onclick="populateFields()>
var index=0;
function populateFields(){
var ft_id = document.getElementById("freq-table");
var alltds = ft_id.getElementsByTagName("td");
for (var i in alltds) {
alltds[i].onclick = function () {
if(index==0) {
searchTerm1.value = this.innerHTML;
} else {
setThis(this.innerHTML);
}
}
}
if (index<2) {
index++;
} else {
index = 1;
}
}
function setThis(value) {
document.getElementById("searchTerm"+index).value = value;
}
When trying to make the function more universal by passing the element id (as follows), it now takes a SECOND mouse click to start populating the fields.
<table onclick="populateFields(this)" id="freq-table">
function populateFields(element){
var alltds = element.getElementsByTagName("td");
What is it about the revision that's changing the behavior? Am I just incorrectly passing the id? Or is revised function now expecting a variable to be passed to it in <body> tag? It's confusing because: If I am incorrectly passing the id, why would the function work consecutively AFTER the first mouse click? What is the fix for this, please?
You have some heavy code here, where the first table click (or body onload) sets additional click event handlers.
What you should do instead is use event delegation. With event delegation, the click event handler is attached to the table but knows which cell was clicked (the target).
[Update] Code sample based on the above article:
var index=0;
var tableIds=["freq-table1","freq-table2","freq-table3"];
for (var i=0;i<tableIds.length;i++) {
var currentId=tableIds[i];
var table=document.getElementById(currentId);
table.onclick = function(event) {
event = event || window.event;
var target = event.target || event.srcElement;
while(target != this) {
if (target.nodeName == 'TD') {
// target is our cell
setThis(target.innerHTML);
}
target = target.parentNode;
}
// increment index modulo 3
index=(index+1)%3;
}; // end of onclick function
} // end of for loop
Live demo: http://jsfiddle.net/srVmF/2/
I think the call can come from the TD or the TR element. So, the first time the id will be 'undefined'.
Why not call the function with the event and verify the tag name:
<table onclick="populateFields(event)" id="freq-table">
Javascript
function populateFields(e) {
var source = e.target || e.srcElement;
if (e.tagName == 'table') {
var ft_id = document.getElementById(source.id);
Instead of being populated on page load, now you have to click on the table before it populates the fields.
You could leave the page load handler:
<body onload="populateAllFields()">
For every table you add a class:
<table class="mytable">
Then, the code:
function populateAllFields()
{
[].forEach.call(document.getElementsByClassName('mytable'), populateFields);
}
Your <body onload="populateFields()> isn't passing the element you want, so the initial set that would be done when the page loads is no longer happening.
You can fix it by passing the ID instead, and give the onload handler the ID.
function populateFields(id){
var ft_id = document.getElementById(id);
var alltds = ft_id.getElementsByTagName("td");
// and so on...
}
<body onload="populateFields('freq-table')">
<table onclick="populateFields(this.id)">