I'm trying to use jquery to set the value of some tags. This is for a the admin side of a wordpress widget which will store a list of records, keyed by a date that are retrieved by using a <select>. In order to achieve this I'm having to to some janky value storage in data-* attributes to link the contents of three hidden <select> lists.
The idea is that the hidden list's values are retrieved by grabbing the visible <select>'s selected <option>'s data-date attribute value and grabbing the <option> in each hidden <select> that has a matching data-date. These values are then put into <input> fields for the user to edit.
HTML fragment
<label for="spdates">Special Dates:</label>
<p>
<select id="spdates">
<option data-date='new' value='new'>New Date</option>
<option data-date='23/05/1992' value='23/05/1992'> 23/05/1992-jake</option>
<option data-date='15/08/1997' value='15/08/1997'> 15/08/1997-rebecca</option>
<option data-date='17/03/1995' value='17/03/1995'> 17/03/1995-clive</option>
</select>
</p>
<p>
<label for="spname">Special Name:</label>
<input class="widefat namspani" id="spname" type="text" value="" />
</p>
<p>
<label for="sptext">Special Text:</label>
<input class="widefat namspani" id="sptext" type="text" value="" />
</p>
<p>
<label for="spdate">Special Date(dd/mm/yyyy):</label>
<input class="widefat namspani" id="spdate" type="date" value="" />
</p>
<p>
<label for="spimage">Special Image:</label>
<br />
<input type="text" class="img anisp" id="spimage" value="" />
<input type="button" class="select-imgsp" value="Select Image" />
</p>
<select id="eventNames" name='widget-dates_widget[__i__][eventNames][]' multiple hidden>
<option data-date='23/05/1992' value='[23/05/1992]jake' selected> jake</option>
<option data-date='15/08/1997' value='[15/08/1997]rebecca' selected> rebecca</option>
<option data-date='17/03/1995' value='[17/03/1995]clive' selected> clive</option>
</select>
<select id="eventText" name='widget-dates_widget[__i__][eventText][]' multiple hidden>
<option data-date='23/05/1992' value='[23/05/1992]yay me' selected> yay me</option>
<option data-date='15/08/1997' value='[15/08/1997]rebecca' selected> rebecca</option>
<option data-date='17/03/1995' value='[17/03/1995]clive' selected> clive</option>
</select>
<select id="eventImages" name='widget-dates_widget[__i__][eventImages][]' multiple hidden>
</select>
Jquery function
$(function() {
//onchange for the date select to populate the other boxes
$(document).on('change', 'select#spdates', function(evt) {
var date = $(this).find(":selected").attr("data-date");
if (date == "new") {
//new date selected, discard what's in the boxes and blank values
$(".namspani").val("");
} else {
//different date selected, discard what's in the boxes and blank values
alert($("#eventNames").find("[data-date='" + date + "']").text());
$("#spname").val($("#eventNames").find("[data-date='" + date + "']").text()); //grab from other lists
$("#sptext").val($("#eventText").find("[data-date='" + date + "']").text());
$("#spdate").val(date);
$("#spimage").val($("#eventImagess").find("[data-date='" + date + "']").text());
}
});
})
I've confirmed my code is being run as I've put an alert() containing one of the values I'm trying to set in the branch of the function i expect to run. In practice the alert files, with the right content, however the input fields don't fill with data.
This code works in jsfiddle https://jsfiddle.net/ForceGaia/j363mv3w/1/ but not natively in firefox or chrome.
What is going on? I'm fairly new to jquery, so I'm now wondering if I'm missing something basic.
EDIT:
The alert fires, so i know it's getting to the right chunk of code, thus some version of JQuery seems to be working. console.log($().jquery); puts 1.12.4 to the log.
I tried putting hardcoded strings into the .var() parameters, still nothing.
I moved the $("#spname") search into a variable to see if it was finding it.
var spnamedom = $("#spname");
After that chunk of code spnamedom was an array of elements (which, knowing jQuery, i expected) I tried accessing the 0th element and it was the correct element.
so i tried both of the following
var spnamedom = $("#spname");
spnamedom.val("a thing");
And
var spnamedom = $("#spname")[0];
spnamedom.val("a thing");
spnamedom is always what I'm expecting, but neither work. There is an element with the correct id in both cases, either as the 0th element, or straight in the variable.
he latter puts TypeError: spnamedom.val is not a function to the log. I assume that error is because I'm no longer in a JQuery object and am looking at a DOM object after i grabbed the 0th element. I could possibly edit this raw DOM element to get what I want, but the initial question remains, why does my code work in jsfiddle, but not a live browser; as from the reading I'm doing, this should work.
I have also found jQuery .val change doesn't change input value and using `.attr('value','text') doesn't work either.
EDIT 2
I realised that in my code i have something that does what i want already on different controls, and it works - which is even more bewildering. I had totally forgotten that the code was performing the same action when it came down to it.
Before i only supplied an exerpt of my JQuery script, here's the entire thing
var image_field;
jQuery(function($) {
$(document).on('click', 'input.select-img1', function (evt) {
image_field = $(this).siblings('.img');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
return false;
});
$(document).on('click', 'input.select-img2', function (evt) {
image_field = $(this).siblings('.img');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
return false;
});
$(document).on('click', 'input.select-img3', function (evt) {
image_field = $(this).siblings('.img');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
return false;
});
$(document).on('click', 'input.select-imgsp', function (evt) {
image_field = $(this).siblings('.img');
tb_show('', 'media-upload.php?type=image&TB_iframe=true');
return false;
});
window.send_to_editor = function (html) {
imgurl = $('img', html).attr('src');
image_field.val(imgurl);
tb_remove();
}
// onchange for the date select to populate the other boxes
$(document).on('change', 'select#spdates', function (evt) {
console.log($().jquery);
var date = $(this).find(":selected").attr("data-date");
if (date=="new") {
//new date selected, discard what's in the boxes and blank values
$(".namspani").val("");
}
else {
//different date selected, discard what's in the boxes and blank values
alert($("#eventNames").find("[data-date='"+date+"']").text());
var spnamedom = $("#spname");
spnamedom.attr('value', 'new value'); //grab from other lists
$("#sptext").val($("#eventText").find("[data-date='"+date+"']").text());
$("#spdate").val(date);
$("#spimage").val($("#eventImagess").find("[data-date='"+date+"']").text());
}
});
});
the code i didn't include is acts on bits of html that look like this
<p>
<label for="s3image">Image 3:</label><br />
<input type="text" class="img ani1" name="widget-namsoc_nextmeet_widget[__i__][s3image]" id="s3image" value="" />
<input type="button" class="select-img3" value="Select Image" />
</p>
What it does is open the Wordpress image uploader dialog when you click a button. When "insert into post" is pressed it sets the path value into the field.
This code works. So what is so different to the other code that makes it fail?
Related
I've tried to search for what I'm after, and this is the closest I can get:
Make a Dropdown with Search Box using jQuery (by Yogesh Singh)
https://makitweb.com/make-a-dropdown-with-search-box-using-jquery/
It can provide a HTML Dropdown with Search capability.
However, what I hope to have is to have input capability as well. I.e., if nothing found, then use the user input as the result.
I tried to look at the code,
$(document).ready(function(){
// Initialize select2
$("#selUser").select2();
// Read selected option
$('#but_read').click(function(){
var username = $('#selUser option:selected').text();
var userid = $('#selUser').val();
$('#result').html("id : " + userid + ", name : " + username);
});
});
UPDATE: using datalist. Requirement:
if found, use found value as the result.
if nothing found, then use the user input as the result.
Maybe both are the same case, but I don't know js well to say that.
$(document).on('change', '#place', function () {
$("#fax").val($("#place").val());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="place" list="places">
<datalist id="places">
<option value="WVC" label="503-882-1212"></option>
<option value="HAM" label="612-883-1414"></option>
<option value="WON" label="317-445-8585"></option>
</datalist>
<br>
<input type="text" id="fax">
I don't see an easy way to do that myself, as I don't know js quite well.
It is possible, to use the user input as the result if nothing found? thx
<datalist> is like a separate select element and linked to the text field previous to it and simply updates the value of textfield based on what is selected. If you like to run your code based on change event on the text field, you need to read the datalist first and then pick the label from it. If there is no value, then pick the text from the textfield.
$(document).ready(function () {
$(document).on('change', '#place', function () {
let myString =
$(this).next().find("option[value='" + $(this).val() + "']").prop("label");
myString = myString ? myString : $(this).val();
$("#fax").val(myString);
$(this).val(myString); //IF YOU LIKE TO SHOW SAME STRING IN TEXT FIELD TOO
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input type="text" id="place" list="places">
<datalist id="places">
<option value="WVC" label="503-882-1212"></option>
<option value="HAM" label="612-883-1414"></option>
<option value="WON" label="317-445-8585"></option>
</datalist>
<br>
<input type="text" id="fax">
I have a three field form. I'd like the third field (text box) to display a combination of the first two fields ... one being a select field and the other being a text field; these values separated with a space. I have tried the following with little success.
<form>
<select name="val1" id="val1">
<option value="">Select a value</option>
<option value="foo">foo</option>
<option value="bar">bar</option>
</select>
<input name="val2" id="val2" />
<input name="val3" id="val3" />
</form>
<script>
$('#val1, #val2').keyup(function(){ $('#val3').val($('#val1').val()+' '+$('#val2').val()); });
<script>
What I'm expecting is when a user selects an option from the select field, is value would appear in the third form field and when a user types something in the second field, its value would also appear in the third field separated with a space. This would all happen in real time. Oddly enough, the jQuery code does nothing in all browsers.
Maybe something to do with the keyup() function as a select field is using the mouse only. But even if I ignore the select field and type something in the second field, it should appear in the third field alone, but it doesn't.
Your #val1 is a select element, the keyup event can't be called with that.
Instead, you neeed to use change event.
$('#val1').change(function () {
changeThird();
});
$('#val2').keyup(function () {
changeThird();
});
function changeThird() {
$('#val3').val($('#val1').val() + ' ' + $('#val2').val());
}
JsFiddle: http://jsfiddle.net/ghorg12110/e7ru9jao/
For asp:TextBox, you need to use .attr() if you want to get the data generated:
$('#val1').change(function () {
changeThird();
});
$('#val2').keyup(function () {
changeThird();
});
function changeThird() {
$('#val3').attr("value", $('#val1').val() + ' ' + $('#val2').val());
}
So I've got an input field that I'm trying to populate using two separate drop-down menus. I've got it working with a single drop-down currently, but I'm unable to do two. Here's an example of what I'm trying to accomplish:
<select type="text" id="make">
<option value="">- select one -</option>
<option value="chevy">Chevy</option>
</select>
<select type="text" id="model">
<option value="">- select one -</option>
<option value="silverado">Silverado</option>
</select>
<input type="text" id="input" value="" />
So the value of the text input should be 'Chevy Silverado' if both fields are selected. Here's the script that I've got so far:
$(function(){
$('select#make').bind('change', function(){
$('input#input').val($(this).val());
});
});
Which works great for one drop down, but obviously does nothing for the other. Any ideas? I've tried a few solutions that I'd found with absolutely no success. Thanks for looking!
Big thanks to those of you who answered my question! With your guidance I was able to get the below code working for me perfectly. Note that I DID add an additional class to my select boxes
$(function(){
var $makemodel = $('.makemodel');
$('.makemodel').on('change',function(){
$('#input').val($makemodel.eq(0).val()+' '+$makemodel.eq(1).val());
});
});
No problem! Please forgive the length of this answer, it offers multiple options depending on whether you place greater importance on code readability vs efficiency. It will only make marginal differences in speed but hopefully it shall inspire you to think of speed in your overall code!
Easy solution:
$('#make,#model').on('change',function(){
$('#input').val($('#make').val()+' '+$('#model').val());
});
More efficient:
Give your selects a class:
<select type="text" id="make" class="MakeModel">
<option value="">- select one -</option>
<option value="chevy">Chevy</option>
</select>
<select type="text" id="model" class="MakeModel">
<option value="">- select one -</option>
<option value="silverado">Silverado</option>
</select>
<input type="text" id="input" value="" />
And then select on the class:
$('.MakeModel').on('change',function(){
$('#input').val($('#make').val()+' '+$('#model').val());
});
Giving it a class just makes it slightly easier for the parser to query only one selector rather than two.
Most efficient:
Use the appropriate .eq() values and caching instead of querying the ID selectors again:
var $makemodel = $('.MakeModel');
$makemodel.on('change',function(){
$('#input').val($makemodel.eq(0).val()+' '+$makemodel.eq(1).val());
});
This means the select items do not need to be requeried since all the objects of .MakeModel are contained within the function under the cached $makemodel and you can just specify the object order number to reference a specific one.
jsFiddle to show what I mean here
Additional notes:
Notice the use of .on rather than .bind, which is the more correct syntax for modern jQuery applications.
Also, using tagnames before ID or class will actually make your selectors less efficient, as the parser needs to verify the ID/class is associated with the tag, rather than just grabbing the ID (which should be unique anyway) or class name (which should be appropriately isolated in its naming).
Simple solution:
$(function() {
$('#make, #model').on('change', function() {
var makeCurr = $('#make').find(":selected");
var madelCurr = $('#model').find(":selected");
var make = (makeCurr.val() != '') ? makeCurr.text() : '';
var model = (madelCurr.val() != '') ? madelCurr.text() : '';
$('input#input').val(make + ' ' + model);
});
});
View Example
I'd suggest amending the HTML somewhat, to group the select elements within a single parent, and binding, using on(), the change event to that element:
<form action="#" method="post">
<fieldset>
<select type="text" id="make">
<option value="">- select one -</option>
<option value="chevy">Chevy</option>
</select>
<select type="text" id="model">
<option value="">- select one -</option>
<option value="silverado">Silverado</option>
</select>
<input type="text" id="input" value="" />
</fieldset>
</form>
With the jQuery:
$('fieldset').on('change', function(){
var self = $(this);
$('#input').val(function(){
return self.find('select').map(function(){ return this.value; }).get().join(' ');
});
});
JS Fiddle demo.
Modifying further, to use a class to identify the summary element (the text-input into which the value will be inserted) reduces the reliance on known elements, and allows for more general-purpose code:
$('fieldset').on('change', function(){
var self = $(this);
self.find('.summary').val(function(){
return self.find('select').map(function(){ return this.value; }).get().join(' ');
});
});
JS Fiddle demo.
And a non-jQuery, plain-JavaScript approach to the same solution (albeit only works in those browsers that support document.querySelector()/document.querySelectorAll() and addEventListener()):
function summarise(container, what, sumClass) {
var els = container.querySelectorAll(what),
sumTo = container.querySelector(sumClass),
vals = [];
for (var i = 0, len = els.length; i < len; i++) {
vals.push(els[i].value);
}
sumTo.value = vals.join(' ').trim();
}
var fieldsets = document.querySelectorAll('fieldset');
for (var i = 0, len = fieldsets.length; i < len; i++) {
fieldsets[i].addEventListener('change', function(){
summarise(this, 'select', '.summary');
}, false);
}
JS Fiddle demo.
I have a dropdown <select> element to select states from the list of 50 states, I select the 1st value, save it, and show the value in DOM. I changed and select to the 5th value, saving it shows the value updates in DOM. Now back i am selecting the 2nd Value, and saving it. It's not saving the value in DOM and it's showing the previous selected 5th value. I Checked with different values, and found that, after selecting any higher index value, selecting back, lower values are not affecting in DOM, and hence i am not getting the correct values in POST.
This is the function i am calling on change.
function updateDOM(inputField) {
var elementId = inputField;
if (inputField.type == "select-one") {
var prev_select = inputField.selectedIndex;
$('#'+inputField.id+' option').each(
function() {
$(this).removeAttr('selected');
}
);
document.getElementById(elementId.id).selectedIndex = prev_select;
if (browserVersion == 9) {
document.getElementById(elementId.id)
.options[prev_select].setAttribute("selected","selected");
}
else {
document.getElementById(elementId.id)
.options[prev_select].setAttribute("selected","selected");
}
document.getElementById(elementId.id).value
= document.getElementById(elementId.id).options[prev_select].value;
}
The HTML
<select id="abc" name="abc" onchange="javascript:updateDOM(this);" class="required" >
<option name="" value="" title="null" selected ></option>
<option name="AK" value="Alaska" title="null" >Alaska</option>
<option name="AL" value="Alabama" title="null" >Alabama</option>
<option name="AR" value="Arkansas" title="null" >Arkansas</option>
<option name="AZ" value="Arizona" title="null" >Arizona</option>
</select>
First of all, why don't you use ":selected" selector of jQuery, which you are using anyway? Also, why are you using jQuery only once?
I would recommend doing it in jQuery-style (sorry, I'm not quite sure what you are trying to do exactly in your code):
http://jsfiddle.net/msLXt/1/
P.S. What is the difference between these conditions?
if (browserVersion == 9) {
document.getElementById(elementId.id)
.options[prev_select].setAttribute("selected","selected");
}
else {
document.getElementById(elementId.id)
.options[prev_select].setAttribute("selected","selected");
}
I have many forms on my site. When the Submit is triggered on the form I expect to receive an id of the form and the option selected.
html
<form name="order">
<select id="count">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select><br/>
<input type="text" name="id" value="6" />
<input href="#" type="submit" value="Submit" />
</form>
JavaScript
var fancyboxOptions = {
ajax : {
type: "POST",
data: {
id: null,
count: null
}
}
}
$(document).ready(function() {
fancyboxOptions.ajax.data.id = $('input[name="id"]').val();
fancyboxOptions.ajax.data.count = $('#count').val();
$('div#buy input').fancybox(fancyboxOptions);
$('#count').change(function() {
fancyboxOptions.ajax.data.count = $('#count').val();
});
With this code I receive only data from the first form -- when the submit is triggered other forms I receive data from the first form rather than from the form I pressed submit on.
How do I restructure my code, so the form submits triggers the submit to give me only the the data in the form for which I pressed submit.
PS Do not pay attention a fancybox, it's work good.
May want to change your code to something like this
<script>
$('input[name=id]').parent().change(function(){
fancyboxOptions.ajax.data.id = $(this).find('input[name="id"]').val();
fancyboxOptions.ajax.data.count = $(this).find('#count').val();
});
</script>
This will install a change handler on each form which contain a input field named id, and the callback function (which is installed on the parent() form ) will have access to "this" which the can navigate the DOM and find all the sub-fields relative to the form node.
Do you need to loop through all the forms on your page and get their values after clicking one button? If so, try this:
$('form').each(function(){
var currentForm = $(this);
var someValue = currentForm.find('input[name="id"]').val();
// do the rest here
});
If that's not your question, then maybe it has something to do with using ids for your inputs instead of classes. You can only use an id once, so if your other forms also include < select id="count"> then when jQuery reads that value, it will only ever return the value of the first one.
Hope this helps...