Objective: I have a list of checkboxes that are loaded onto the HTML DOM via JSON and javascript. The checkbox buttons will load onto the page fine but if I use my other function uncheckAllCities(), all of the buttons will disappear from the display, not uncheck them. I am not sure why. It happens for several other actions such as when I ask it to do the calculations the check buttons go missing. Perhaps it has to do with how I added the checkboxes from the JSON to begin with.
Any ideas why the buttons disappear from view?
The following functions generate the checkboxes...
function buildCheckBoxes() {
JSONCities = [ //Build checkbox controls to choose which cities get APIs
{
"CityName": "Bellaire",
"LatLong": "47.1200,-88.4600",
"index": "a",
"checked": "checked"
}, ...(more JSON code)...
},
];
//Form a list of checkboxes from JSON
for (j = 0; j < JSONCities.length; j++) //Need to learn if value may be set in checkbox to return, not just true and false checked
{
loadChk = '<input class="checkboxes_class" type="checkbox" name="checkbox-v-2' + JSONCities[j].index + '" value="' + JSONCities[j].LatLong + '" id="checkbox-v-2' + JSONCities[j].index + '"' + JSONCities[j].checked + '>' + " " + '<label for="checkbox-v-2' + JSONCities[j].index + '">' + JSONCities[j].CityName + '</label>';
locCheckBtn += loadChk;
}
$('#loc1').html(locCheckBtn); // update HTML DOM
}
$(document).ready(function() {
//prepare checkbox buttons on page load.
buildCheckBoxes();
});
function uncheckAllCities() { //stackoverflow.com/questions/14110169/check-uncheck-the-array-of-checkboxes
document.getElementsByClassName("checkboxes_class").checked = false;
}
Playing around with your code I found two problems:
I already mentioned this in a comment: getElementsByClassName returns a collection, not an element, so you should loop over it and set checked = false to each individual element.
By default all html buttons are submit-buttons. Therefore as soon as you click any button the form will be submitted, resulting in the page being refreshed. If you add the type="button" attribute to each button the form won't be submitted when you click on them (e.g. <button type="button">click here!</button>). (Small sidenote: I'm not really sure why the checkboxes don't load after the form has been submitted, but setting the type to button should at least solve your problem so I didn't investigate that any further)
Related
I am trying to create a dynamic show-more and less content option using jquery. The problem is my results are coming from a for loop, so how can I force jquery that on page load to load only 20 results and then load the rest when I click show more button. Also the button should change to "show less" when the list is expanded and clicking on it will return to show just first 20 results. Below is my code
HTML
echo html_writer::start_tag('div', array('id' => 'establishment'));
echo html_writer::start_tag('h5');
echo get_string('institutions', 'block_solr');
echo html_writer::end_tag('h5');
echo html_writer::end_tag('div');
jQuery
var institutionList = $.getJSON({'url': location.protocol + '//' + location.host + currentdirpath + '/establishment.json', 'async': false});
institutionList = JSON.parse(institutionList.responseText);
console.log(institutionList);
for (var i = 0; i < institutionList.data.length; i++) {
$('#establishment').append('<div class="form-check"> <input class="form-check-input size-filter-check" type="checkbox" value="'+ institutionList.data[i].altname +'" id="est-check" data-size="">\n' +
' <label class="form-check-label" for="size-check">\n' + institutionList.data[i].fullname +
' </label> </div>');
}
$('#establishment').append('Show More');
If you want to query for specific amount that data source should be prepared for it. If you don't mind over fetching you can just hide/show that additional records on FE side.
// keeping some state would help
let listExpanded = false;
// wrapping all rendering procedure in one function too
function renderInstitutionList() {
//here you clear previous render
$('#establishment').empty()
// you can trim your array to certain size with code below
//[...] syntax is to avoid mutating original list
[...institutionList.data].splice(0, limit)
// and here you do your thing with the loop
}
There are tons of other solutions though. You could probably do that just with html/css
Good morning Stack Overflow,
This will be my first question and I am still learning coding, so please forgive me if I'm ever being naive.
I am currently working on a modal that the user is shown when they're trying to pick quantities of a certain product from a warehouse that has been stored in multiple locations.
The user is given a requested quantity and the drop down menu shows each of the possible locations that they can retrieve an item from. The user will then select the location using the select menu and then adjust the slider with the amount they want to take from that location.
If the user wants to split the requested amount across multiple locations however, they will click the "Pick Another Location" button and another row containing the select menu will appear directly underneath. The user will be able to do this until the total picked has reached the Quantity Requested or until they run out of locations to pick from. My problem is, I am trying to remove the location the user selected prior to clicking the "Pick Another Location" button.
As you can see the same location appears again in the appended menu. I would like to have it so it doesn't. Its turning out to be quite difficult for me because each location picker has a unique ID that is created with a variable and I find it difficult to implement that into any types of condition usually.
I had a similar issue with the Quantity slider, as I was trying to treat each slider individually, but also contribute as a collective. Anyway, starting to get off topic and ramble.
I will show below the code which I feel may help...
Initial creation and variables declared:
//Multiple Location PopUp Function
jQuery.LocPick = function LocPick(id){
//Function Post
$.post(base_url+"ts/TestedQtyMultiLoc/", {
ID: id,
BatchID: $("#BatchID").val()},
//Calling variables to be displayed within the PopUp
function(data){
QtyReq = data.item.QtyRequested;
var code= data.item.ItemCode;
rowCount = $('#AddLocationPicker tr').length;
loc='';
$.each(data.Locations, function(i, value) {loc +='<option value="'+ value.Location + '">' + value.Location + ' -- Qty: ' +value.Qty +'</option>';
})
Picker=0;
This is the code for the HTML contents of my modal:
//PopUp Contents
$("#dialog-ProcessConfirm").html('<p>'+code+' has multiple locations<br><br>Please confirm which locations the item is to be picked from before continuing.</p><p><table id="AddLocationPicker"><tr><td></td><td>Location</td><td>Qty Picked</td></tr><tr id="' + Picker +'"><td></td><td><select class="selectbox" id="LocationPickerSelect'+ Picker +'"><option value="0">Please select a location'+loc+'</option></select></td><td><input class= "QtyPicker" id="AddLocQtyPick'+ Picker +'"type="number" min="1" max='+QtyReq+' value="1" onkeydown="return false"></td></tr></table><table><td></td><td>Quantity Requested:</td><td>'+QtyReq+'</td></table><table><td></td><td><input type="text" name="LocErr" id="LocErr" maxlength="50" size="50" tabstop="false" readonly="true" style="border:0px;color:#FF0000;" value=""><input type="text" name="QtyErr" id="QtyErr" maxlength="50" size="50" tabstop="false" readonly="true" style="border:0px;color:#FF0000;" value=""></td></table></p>');
}, "json");
The "Pick Another Location Button":
//Buttons for the PopUp
buttons: {
'Pick Another Location': function() { //Button to allow user to add another location to pick from
$('#AddLocQtyPick'+Picker).prop ('disabled', true); //Disables the current selection, so that it cannot be edited
$('#LocationPickerSelect'+ Picker).prop ('disabled', true); //Disables the current selection, so that it cannot be edited
Picker++; //Adds Unique Number to the ID of the input fields
//For Loop that helps to total up the quantities being selected in each picker
total=0;
for (i = 0; i<Picker; i++) {
total= total + $('#AddLocQtyPick'+i).val() * 1.0;
}
QtyReqTot= QtyReq - total; //Variable decides max value of pick on appends using previous selection
What gets appended:
//The Location/Quantity Picker that gets appended
var appendTxt = '<tr id="' + Picker + '"><td></td><td><select class= "selectbox" id="LocationPickerSelect'+ Picker +'"><option value="0">Please select a location'+loc+'</option></select></td><td><input class= "QtyPicker" id="AddLocQtyPick'+ Picker +'" type="number" min="1" max='+QtyReqTot+' value="1" onkeydown="return false"></td></tr>';
I didn't know if I could use the same sort of technique in using For Loops to use with the incrementing IDS that the Location Picker has, like I did with the Quantity slider as I've seen some examples that suggest this whilst others have said to never use loops in this situation.
My main issue boils down to how I can select an option in one unique menu and remove that option from another unique menu that has the same options.
I'll thank you now for any input/advice received and for patience in my abilities!
EDIT: Problem Solved
The problem I was having did involve trying to take the unique ID's into consideration when writing my syntax. Confirmation for the use of a for loop allowed me to compare with my previous loop I created when totalling the picker quantities.
//For Loop that removes previously selected locations from the append
for (i = 0; i<Picker; i++) {
LocSelect= $('#LocationPickerSelect'+i).val();
$('#LocationPickerSelect'+Picker+' option[value="'+LocSelect+'"]').remove();
}
I will suggest to go with following approach:
Instead of simply adding all the <option> to each select box like below:
$.each(data.Locations, function(i, value) {loc +='<option value="'+ value.Location + '">' + value.Location + ' -- Qty: ' +value.Qty +'</option>';
})
Go for following code which check; which all <option> are already been selected by end user. And adds only those which are unused previously.
var prevSelectedLoc = [];
if(Picker > 0)
{
for(i=0;i<Picker;i++)
{
prevSelectedLoc.push($("select#LocationPickerSelect"+i).val());
}
}
$.each(data.Locations, function(i, value) {
if($.inArray(value.Location,prevSelectedLoc) == -1)
{
//if current option has not been previously selected then only add it to current select box
loc +='<option value="'+ value.Location + '">' + value.Location + ' -- Qty: ' +value.Qty +'</option>';
}
});
The problem I was having did involve trying to take the unique ID's into consideration when writing my syntax. Confirmation for the use of a for loop allowed me to compare with my previous loop I created when totalling the picker quantities.
//For Loop that removes previously selected locations from the append
for (i = 0; i<Picker; i++) {
LocSelect= $('#LocationPickerSelect'+i).val();
$('#LocationPickerSelect'+Picker+' option[value="'+LocSelect+'"]').remove();
}
I'm working with Zend Framework 1.12 and I've need to be able to dynamically add and delete fields from a sub-form, in this case we're associating hyperlinks to a parent "promotion".
I haven't found a way to accomplish dynamically adding and removing elements via Zend, and the rare tutorial I've found that claimed to do this are half a decade old and aren't working when I attempt them.
So what I am doing is storing the links I need to work with in a Zend Hidden input field and then dealing with the JSON data after I submit. Not very efficient, but it's the only thing I've gotten to work so far.
Below is the section of the code I'm working with:
Assume a form like:
<form action="/promos/edit/promo_id/15" method="POST" id="form_edit">
<!-- input is Zend_Form_Element_Hidden -->
<input type="hidden" id="link_array" value="{ contains the JSON string }"/>
<button id="add_link">Add Link</button>
</form>
The purpose is that every time the Add Link button is pressed, the form adds fields to allow the user to input new hyperlinks that will be associated with the specific items.
Here's the function:
// add links
$('#add_link').click(
function(e) {
e.preventDefault();
link = '<div class="p_link new_link">' +
'<div class="element_wrap">' +
'<label for="link_name" class="form_label optional">Text: </label>' +
'<input type="text" id="new_link_name" name="link_name"/>' +
'</div>' +
'<div class="element_wrap">' +
'<label for="link_http" class="form_label optional">http://</label>' +
'<input type="text" id="new_link_http" name="link_http"/>' +
'</div>' +
'<div class="element_wrap">' +
'<button class="submit delete_link">Delete</button>' +
'</div>' +
'</div>';
$('#add_link').prev().after(link);
}
);
Now, what I need to do is on submit, for every new_link class element, to take the links name and http reference and place it in a json object. Here's the code as I have it so far (I know I don't have both input fields represented at this point):
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = document.getElementsByClassName('new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).children('#new_link_name').text();
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
My problem is that: var new_links = document.getElementsByClassName('new_link'); will collect all the newly added new_link elements, but it does not pull in any value that has been input into the text fields.
I need to know how I can apparently bind any input I make to the input field's value attribute, because right now anything I type into these new elements are tossed out and the field appears empty when it's anything but.
$('#submit').click(
function(e) {
e.preventDefault();
var link_array = [];
var new_links = $('.new_link');
$.each(new_links, function() {
console.log(this);
var n = $(this).find('input').val(); // you need input values! This line //is changed...
console.log(n);
link_array.push({'link_name':n}); //'link_http':h
});
console.log(JSON.stringify(link_array));
}
);
JSFIDDLE: http://jsfiddle.net/DZuLJ/
EDit: You can't have multiple IDS (make class for each input, and target class, if you want link names and http's)
My application successfully creates elements and assigns them different (increasing) IDs.
Now my issue relies when the user deletes these elements (because they have the option to delete as well as create), the consistency of these IDs get broken therefore my application doesn't run well.
This Fiddle represents what I have so far. Just a textbox that appends its value and a few other elements inside a collapsible as many times as the user wants (For some reason my fiddle doesn't increment the alert value, but it works fine on my platform).
SCRIPT (Sorry the txt variable is too long)
$('#Add').click(function () {
if ($("#MedNameStren").val() != "") {
var value = $("#MedNameStren").val();
var noOfMeds = $('#NoOfMedicines').val();
//to check current value
alert(noOfMeds);
var text = '<div data-role="collapsible" data-collapsed="true" data-iconpos="left" data-content-theme="e">' + '<h2>' + desc + '</h2>' + '<div class="ui-grid-a">' + '<div class="ui-block-a" style="width:25%; margin-right:3%;">' + '<input id="quantity' + noOfMeds + '" class="quantity" type="text" placeholder="Quantity" />' + '</div>' + '<div class="ui-block-b" style="width:70%; margin-right:2%;"">' + '<textarea id="directions' + noOfMeds + '" class="directions" cols="40" rows="4" placeholder="Directions given by your GP." ></textarea>' + '</div>' + '</div>' + '<button key="' + vpid + '">Remove</button>' + '</div>';
$("#medListLi").append(text);
$('button').button();
$('#medListLi').find('div[data-role=collapsible]').collapsible();
$('#medListLi li').listview("refresh");
$('#medListLi').trigger("create");
document.getElementById("manuallyName").value = "";
noOfMeds++
$("#NoOfMedicines").val(noOfMeds);
}
else {
alert('Please Provide Medicine Name')
}
});
I am using a counter that neatly increments the ids of quantity and description like:
quantity0
quantity1
quantity2
..and so on, but once the following script is called...
//Deletes colapsible sets (Medicines) from the selected List
$('#medListLi').on('click', 'button', function (el) {
$(this).closest('div[data-role=collapsible]').remove();
var key = $(this).attr('key');
localStorage.removeItem(key);
var noOfMeds = $('#NoOfMedicines').val();
noOfMeds--
$("#NoOfMedicines").val(noOfMeds);
//location.reload();
});
depending on which element (collapsible) is deleted, the IDs stop being consistent. For example if the collapsible with id="quantity1" is deleted then the counter will go back to 1 (currently 2) and on the next addition the respective collapsible will get an id that's already taken, and unfortunately I don't need this to happen.
Maybe I'm making this sound more complicated that it is, but will appreciate any suggestions or ideas to solve this issue (if possible).
If more information is needed, please let me know.
Was brought to my attention that creating and deleting dynamic IDs can be done but keeping up with consistency of these IDs can be very tricky to work around it.
I've solved my own problem by simply creating a function that would keep count of the IDs from the amount of collapsibles inside my list and "renewing" the ID numbers on each Add and Delete.
Using Kendo UI and a Row Template, I have a grid started like the following:
http://jsfiddle.net/xF4CK/
I'm wanting to alter the Actions column to contain a drop down list populated by the actions object. The actions object contains display text and a relative url path like the following example:
var actions = [
{ name: "edit", url: "reports/report/1" },
{ name: "delete", url: "reports/delete/1" }
];
This actions object is on each row of the grid and may vary per row/user/etc. The intended usage would be a user selects the drop down list and then chooses one of the options. On choosing the option the url value is posted.
I'm not sure where to begin, or if it is possible in the Row Template. Any help is greatly appreciated.
I was able to get it figured out. In the row template I am calling a js function and returning html markup for the list. Then setting the .kendoDropDownList on all items based on a class attribute. I have updated the jsfiddle here but it doesn't seem to work in jsfiddle. It is working when I test in IE10 and Chrome on my dev machine.
Here's the relevant code changes:
In the rowTemplate, changed
#: actions #
to
#= renderDropDown(actions) #
This "=" displays the literal text which renders the html as html whereas the ":" encodes the html.
The renderDropDown function:
function renderDropDown(actions) {
var dropDownList = "<select class=\"insight-dropdown\">";
dropDownList = dropDownList + "<option value=\"default\" disable=\"disabled\">...</option>";
for (var i = 0; i < actions.length; i++) {
dropDownList = dropDownList + "<option value=\"" + actions[i].url + "\">" + actions[i].name + "</option>";
}
dropDownList = dropDownList + "</select>";
return dropDownList;
}
To the dataBound event of the grid, I added this function to turn the html into a drop down list:
// Set the drop down lists
$(".insight-dropdown").kendoDropDownList({
select: onDDLSelect
});
To handle the selection of an action:
function onDDLSelect(e) {
var dataItem = this.dataItem(e.item.index());
alert(dataItem.value);
}