I have some web pages which display a number of (up to several dozen) work items.
Each work item is a form consisting of several fields, two of which are large selects (one about 350 items and the other about 650 options) which are always identical other than the initially selected item.
The page can be pretty slow to load. Some of this may be due to the 24KB + 52KB of html for each copy of those selects, and I'm betting a fair amount of it is the time for the browser to build what is essentially the same huge chunk of (mostly of no interest) DOM over and over again.
What I'm thinking might be better is to just keep a master copy of the options for each in an array and just start each select out with only a single option (the initially selected value), For example:
<form ...>
<input ...>
<select class='dept_select' id='dept' name='dept' size='1'>
<option value='12345' selected>Department of Banking and Finance
</select>
<select class='approver_select' id='approver' name='approver' size='1'>
<option value='jpflat' selected>J. Pierpont Flathead
</select>
</form>
and then when the user clicks on the one selectbox they are interested in, build the rest of it from the array. Is this at all sensible, and if it might be, is there some clever and succinct way to do this in jQuery or am I going to have to invent it from whole cloth and raw JavaScript? FWIW, there's no real correlation between the selects (e.g., like selecting a state limits the valid choices for selecting a city).
I'm not going to post code so far. I recommend to re-build your concept a bit to get to a simpler structure:
A user can only edit one item at a time. There's no need to generate "a couple of dozen forms", as long as no edit action is taken.
render the items as a simple two-dimensional array with rows and fields, preferable in a JSON
built the table of items dynamically in the client by use of jQuery
if the user wants to edit an item, open a div layer, render a form into it by the use of the above array. Of course with just one single set of these dropdowns.
consider to load these dropdowns on request by AJAX or use some "combo box" features like in jQuery ui (below).
on "save" submit the form and close the div layer
There are certain containers and dialogs ready-to-use in jQuery ui to achieve this. The result will be
more generic code
less html overhead
better usability even
Well, turns out it wasn't as hard as I was imagining it...
<form ...>
<select id="ts" name="ts" size="1" class="tsc">
<option value="12345" selected>This is the initial value</option>
</select>
</form>
and:
var arr = [
{V:'alpha',T:'One'},
{V:'bravo',T:'Two'},
{V:'charlie',T:'Three'}
];
$(function() {
$( '.tsc' ).mousedown(function() {
var sel = $(this);
sel.unbind('mousedown');
$(arr).each(function() {
sel.append($('<option>')
.attr('value', this.V)
.text(this.T));
});
});
});
jQuery rocks.
Related
for example - a profile page - users want to change some values in select tags
you cannot say - <select id='lorem' value='ipsum'>
you must go to javascript - $('#lorem').val('ipsum')
is this really true ?
is there any better practice - if you have a lot of select tags ?
btw - why html developers made this like this - there must be some strong reason
Your "question" really embodies multiple questions, hence I divided my answer into multiple sections.
<select> and <option>
To select an <option> of <select> initially, add the selected-attribute to <option>. Selecting an <option> makes the <select> have the value of the selected option.
var select = document.querySelector('select');
var code = document.querySelector('code');
select.addEventListener('change', () => code.textContent = select.value);
code.textContent = select.value;
body {display:flex;align-items:center;gap:0.5rem}
code {padding:0 0.2rem;background:lightgray}
<select>
<option value="first">First option</option>
<option value="second" selected>Second option, initially selected</option>
<option value="third">Third option</option>
</select>
<span>Select's 'value': <code></code></span>
Giving <select> a value-attribute will be ignored by the browser-engine, since HTML5 doesn't specify the <select>-tag to have a value-attribute.
Note: The HTML-attribute value and the JavaScript property .value are not necessarily related to each other.
See this example for reference:
var select = document.querySelector('select');
var code = document.querySelector('span > code');
select.addEventListener('change', evt => {
code.textContent = evt.target.value;
});
code.textContent = select.value;
body {display:flex;flex-flow:column;align-items:flex-start;gap:0.5rem}
code {padding:0 0.1rem;background:lightgray}
<div>
<code><select></code> has the attribute <code>value="from-select"</code>.
</div>
<select value="from-select">
<option value="from-opt1">Opt1</option>
<option value="from-opt2">Opt2</option>
</select>
<span>Select's 'value': <code></code></span>
To change the value of an <option> dynamically, you would have to use JavaScript.
var input = document.querySelector('input');
var option = document.querySelector('option');
var code = document.querySelector('code');
// Ignore; update 'pre.textContent' when changing 'value'
option.setAttribute = function(name, value) {
HTMLElement.prototype.setAttribute.call(this, name, value);
if (name === 'value') code.textContent = value;
};
// How to change the 'value'-attribute using JS
document.querySelector('button').addEventListener('click', () => {
option.setAttribute('value', input.value);
input.value = '';
});
body {display:flex;flex-flow:column;align-items:flex-start;gap:0.5rem}
code {padding:0.1rem 0.2rem;background:lightgray}
<span>
<input>
<button>Change value of 'Option'</button>
</span>
<select>
<option value="initial-value">Option</option>
</select>
<span>Option's value: <code>initial-value</code></span>
Regarding "why html developers made this like this"
Paraphrased: Why can't HTML change its markup on its own?
Reason is, HTML was initially created for scientific documents served via the internet.
Since the internet is by nature a web of interconnected, potentially completely different devices, HTML had to be as unspecific and "device-agnostic" as possible, to allow rendering it on virtually any device that has a display.
For that reason, any further resource (e.g. stylesheets, scripts, images) should only be optional for the rendering of the HTML, as the HTML should be renderable "as is".
HTML should also be backwards-compatible, meaning that future changes to the HTML specification should in no way hinder the serving of the HTML. That means, any unknown... thing, basically, will be ignored by the rendering engine (todays browsers) so that all the then-existing features can still work as intended.
Initially, HTML was not intended to have any further functionality than serving static content. However, over the last few decades, the internet has had its "boom" of technological advancement, and now, JavaScript is de facto part of any browser-engine and website, enabling them to have advanced functionality and be interactive.
The internet is in a state of ongoing development, and always will be. Neglecting the new state of the internet and its specification (e.g. for the browser-engines, etc.) would mean that one is not moving with the times, withholding new, modern and current information and knowledge from oneself, essentially leaving one behind.
"Tradition" is difficult to find in any technical field, as new advancements and discoveries are simply spoken part of them.
To learn more about the roots of the internet (even though the video is thematically about CSS) I recommend watching MDN's video about why CSS is weird (and how HTML came to be).
Regarding your "question" ...
as you have further explained in the comments:
I have some data about each user in database. Those data are from
registration form. That form has select tags. Now, user want to change
some data on his profile. Tha data need to be presented on select
tags. It would be normal to do that using value attribute, like in any
other input - without javascript
You could do it two ways:
Create a <form> with one field for each user-data. With this, you have two more options:
Prepare the fields to hold their current data. The user can then submit his changes easily.
Leave the fields empty. If a field is empty after submission, ignore the proposed "change".
Let the user select what data to change one at a time. Again, two more options to achieve this:
Fetch the current data for that field. The user can change it and then submit it easily, again.
Let the user enter the new data anew, then submit it.
Here is a simple example of how the HTML for option 2.2 could look when implemented:
Note: I changed the <button>'s default type from type="submit" to type="button" for demonstration-purposes.
var select = document.querySelector('select');
var input = document.querySelector('input');
document.querySelector('button').addEventListener('click', () => {
console.log(`Would change user-data '${select.value}' to the value '${input.value}'.`);
});
<form>
<select>
<option value="name">Name</option>
<option value="address">Address</option>
<option value="email">E-Mail</option>
</select>
<input>
<button type="button">Submit</button>
</form>
I have something in my mind, but I have no idea how to get it done, so I hope I can get some advise here.
I'm working on an activity registration app (using Laravel), where every activity will be registered. Very important is that we need to record who was invited and who actually attended. I already have this part running. My issue is more on the practical side.
I use jQuery Select2 for the multiple select fields for invitees and attendees. Imagine now that there's a group of users that need to be invited or attend virtually all activities, while the invitation or attendance of others depends on the type of activity. Using Select2, I can only select users one at a time and that sucks if you need to do that for, say, 50 users for virtually every activity.
What is the best way to have a "group" that can be selected, which selection fills in all the names of those in the group in the select field? Or is there a better way to get this done?
I'm seeing something in my head, where there are checkboxes next to the select field, representing the groups. When you tick a checkbox of a group, the select field is populated with all users who are part of that group.
I have no idea ow this can be done. I looked around and every search brings up select boxes populating select boxes. None handle checkboxes.
Any advise on how to get this done?
My PHP/MySql is intermediate, Javascript/Ajax is very basic.
One strategy would be to build a control (checkbox element) that will set or toggle the selection of your group of users whenever it's clicked. Say we have the following markup:
<select class="my-big-group-select" multiple="multiple">
<!-- assorted options here -->
</select>
<label>
<input type="checkbox" class="toggle-default-group" />
Use my default big group of users
</label>
The Select2 API allows you programmatic control over the component it generates.
You can read more about it here: https://select2.github.io/examples.html#programmatic
Here's one way to leverage this knowledge using jQuery with Select2:
<script>
var groupSelect = $('.my-big-group-select').select2();
var groupToggle = $('.toggle-default-group');
var myBigGroup = ["Aaron", "Beth", "Cindy"]; // assorted option values
groupToggle.on("click", function() {
if ($(this).is(':checked')) {
groupSelect.val(myBigGroup).trigger('change');
} else {
var currentlySelected = groupSelect.val();
if (currentlySelected) {
var filteredSelections = currentlySelected.filter(function(key) {
return myBigGroup.indexOf(key) < 0;
});
groupSelect.val(filteredSelections).trigger('change');
}
}
});
</script>
Here's a CodePen that shows it all in action: http://codepen.io/anon/pen/qNQKOd
Of course you can build on this to make additional enhancements (the ability to select multiple groups, for example).
As an alternative, you may consider other code libraries like Bootstrap Multiselect: https://davidstutz.github.io/bootstrap-multiselect/
Hope this points you in the right direction!
So, What I'm trying to do is fairly simple with vanilla JS, but I'm using AngularJS and I would like to know how to do it the best way within the framework. I want to update the selected options in a multiple select box. I do not want to add or remove any of the options. Here is what my HTML looks like:
<select multiple>
<option value="1">Blue</option>
<option value="2">Green</option>
<option value="3">Yellow</option>
<option value="4">Red</option>
</select>
Using the following array, I'd like to programmatically select/deselect options from this list:
[{id:1, name:"Blue"},{id:4, name:"Red"}]
When I set this array in the scope, I want the select box to deselect anything that is not Blue or Red and select Blue and Red. The standard response that I've seen on the Google Groups is to use ng-repeat. However, I can't recreate the list every time because the list of selected values is incomplete. As far as I can tell, AngularJS has no mechanism for this, and I'm at a loss as to how I would do this without resorting to using jQuery.
ngModel is pretty awesome! If you specify the indexes as a model selectedValues
<select multiple ng-model="selectedValues">
built from your list (selected) in a $watch
$scope.$watch('selected', function(nowSelected){
// reset to nothing, could use `splice` to preserve non-angular references
$scope.selectedValues = [];
if( ! nowSelected ){
// sometimes selected is null or undefined
return;
}
// here's the magic
angular.forEach(nowSelected, function(val){
$scope.selectedValues.push( val.id.toString() );
});
});
ngModel will automatically select them for you.
Note that this data binding is one-way (selected to UI). If you're wanting to use the <select> UI to build your list, I'd suggest refactoring the data (or using another $watch but those can be expensive).
Yes, selectedValues needs to contain strings, not numbers. (At least it did for me :)
Full example at http://jsfiddle.net/JB3Un/
I am doing a holiday booking form using RS Form with Joomla whereby I want answers from previous questions to automatically populate the answer for other questions so that, for example, the answer to 'what airline is person 1 travelling on?' automatically populates the answer to 'what airline is person 2 travelling on?'.
I am able to do this for simple text fields when a check box (id=samedetails20 in code below) is checked. When checked, the following works:
<script type="text/javascript">
function repeat(f) {
if(f.samedetails20.checked == true) {
f.airline2.value = f.airline1.value;
f.Airport2.value = f.Airport1.value;
f.flightno2.value = f.flightno1.value;
f.airlinereturn2.value = f.airlinereturn1.value;
}
}
</script>
HTML
<input type="text" value="" size="20" name="form[airline2]" id="airline2" class="rsform-input-box">`
However, the form also includes a drop down list to select arrival/departure times and a pop up calendar for arrival/departure dates. I do not know how to get the values from these to automatically populate the other fields.
I have tried to use selectedIndex and options but this does not work or I am doing something wrong e.g.
f.DepartureTime2.value = f.DepartureTime1.options[f.DepartureTime1.selectedIndex].value;
Sample HTML
<select name="form[DepartureTime2][]" id="DepartureTime2" class="rsform-select-box"><option value="00">00</option><option value="01">01</option>
<option value="02">02</option><option value="03">03</option>
etc.
I also have no idea how to do this for the pop-up calendar:
Sample HTML:
<input id="txtcal9_1" name="form[dateofdeparture1]" type="text" class="txtCal rsform-calendar-box" value="Departure date"> (Departure Date is a default value until date is selected)
Any help much appreciated.
Javascript is client-side only. No values are sent to the server, and JS must work with only what it's got on the client machine (that is, what it's received from the server).
This means that when the new page is sent after a page reload (like a refresh or form submit or new window), Javascript is sent fresh values. The old ones are gone, unless your browser ( = client side) remembers what you typed in an <input> box for some reason.
So, no, you can't do this in just Javascript. You'll need something server-side like PHP or ASP or JSP to receive your values server-side, process them, and send them back to the client for Javascript to use.
I know this has been asked before, however I cannot find a solution to my problem.
I have a select box with three options and three values, these values are used to perform some calculations using JS so I cannot change these to match the option text. This is to work out the amount of V.A.T.
My select looks like this:
<select name="tax" id="tax" class="select">
<option value="20">Standard 20%</option>
<option value="0">Zero 0%</option>
<option value="0">Exempt 0%</option>
</select>
Which is fine, however I need to insert the text into the database and not the values, as it needs to be viewed in the backend. I have tried a javascript function to add a hidden input to the select box targeting the option that is selected but that was a bit buggy, and didn't seem right. i was thinking of displaying the text next to the value when it is retrieved from the database, however I wouldn't be able to distinguish from the two 0 amounts.
Could someone please offer some further solutions, best approaches to this.
Many Thanks
You can get the text of the selected option with jQuery as follows:
$("#tax option:selected").text();
You could easily use this within your AJAX request to send the correct value to the database, just assign it to a variable:
var the_text = $("#tax option:selected").text();
Failing that, why not just do the lookup in the JS calculations - it'd make your life so much easier:
<select name="tax" id="tax" class="select">
<option value="standard">Standard 20%</option>
<option value="zero">Zero 0%</option>
<option value="exempt">Exempt 0%</option>
</select>
And your JS could look something like this:
var vat_amount = ($('#tax').val() == 'standard') ? 20 : 0;
You can retrieve the text by JS using the html() function. Or, if you are just using a POST to send the data to the server, try adding both values to the value attribute of the option and split it server side to get the right data.