why do onchange and onblur only work sometimes? - onchange

My form has a small number of fields where the user can add values like this one
<input name='extracost' type='text' size='25' id='extracost' value='$extracost' onChange='calculate();' >
Problem is that with onBlur or onChange only 'seem' to work once. If the element extracost starts as 0 or null, for example, if I change it on form to 50, the function seems to work correctly and total increases by 50. But if I set it back to 0, it does nothing. If I set it again to -50 it will subsequently work.
If I set the extracost to 50, then 60, then 70, the total goes up by 180.
here is the relevant javascript
var subtotal = document.getElementById("subtotal").value;
var extracost = document.getElementById("extracost").value;
var total = Number(subtotal) + Number(extracost);
document.getElementById("total").value = total;
I've read lots of threads here with a similar problem but none of the solutions have worked.

First of all, you don't have onBlur event in your source code.
In addition, try to parse the textbox value:
var subtotal = parseInt(document.getElementById("subtotal").value, 10);
var extracost = parseInt(document.getElementById("extracost").value, 10);
var total = (subtotal) + (extracost);
document.getElementById("total").value = total;
I would think you are having the issue in Chrome. Finally, onChange and onBlur only work when your cursor goes off the textbox.

The solution to my problem was found by eliminating this
var subtotal = parseInt(document.getElementById("subtotal").value, 10);
and gathering all the individual form variables used to calculate subtotal, and simply recalculate it.

Related

v-text-field oninput handler for max quantity only handles it once

I'm using a v-text-field with an input handler that prevents entering too high of a value. E.g. max quantity is 50, so my handler will set the quantity to 50 if user enters 98 or if they enter a non numeric value. However the handler will only do so once. After that, the value technically remains 50, but the field will show the user's input.
It doesn't seem to be an issue if I use the native html , anyone know how to deal with this in Vuetify? I've added a link to the sandbox below:
https://codesandbox.io/s/v-text-field-issue-w43sx?file=/src/App.vue
You should use #change instead of #input. Input fires once you starts typing. Change will be watching for any changes.
And in check parseInt. Vuetify automatically renders model text as a string. In start 0 will be "0".
<v-text-field
v-model="quantity"
label="Quantity"
#change="preventOverflow"
/>
preventOverflow() {
if (parseInt(this.quantity) > 20) {
this.quantity = 20;
}
},

Dynamically Creating Filename for Button OnClick

I have a family tree website and want to show all events in our family on the current date (Month and Day). So, if today's April 3rd, I want to show all events in our family that occurred on April 3rd.
I've played with creating a table and hiding rows, etc. but the table's too big and it's taking too long. So, I've decided to create a separate .htm file for each day of the year (i.e., todayinhistory-0101.htm, todayinhistory-0102.htm, etc.).
I have a button which, when clicked, is to get the current date in MMDD format and then open the correct file.
I have the script to get the correct filename using the current date in MMDD format, but I can't figure out how to call it and make it work.
Right now, my button looks like this:
<button onclick="location='GetTodayInHistoryFilename()'">
GetTodayInHistoryFilename() is a function I know works. I just can't get the button format right to call it.
Obviously, I'm a novice and would appreciate anyone's help.
In case you're interested, here's GetTodayInHistoryFilename() - which is loaded in the page's header section:
<script type='text/javascript'>
function GetTodayInHistoryFilename()
{
var Today = new Date();
var TodayMonth = Today.getMonth()+1;
var TodayDay = Today.getDate();
if (TodayMonth < 10) { TodayMonth = '0' + String(TodayMonth); } else { TodayMonth = String(TodayMonth); }
if (TodayDay < 10) { TodayDay = '0' + String(TodayDay); } else { TodayDay = String(TodayDay); }
return 'todayinhistory-' + TodayMonth + TodayDay + '.htm';
}
</script>
Thanks in advance.
I'm not 100% sure this is what you're trying to do but I think you want the button click to navigate to another HTML page in which case - you're not far off:
<button onclick="window.location=GetTodayInHistoryFilename()">
Explanation: You're setting the location property of the window object (your browser's top level frame, in this case) to (a new url). You've defined this using your function which is fine. The only mistake you made was to include the function in quotes. This meant that function name was treated as a literal text string rather than an executable function.
You may or may not need to specify window. (the global object) in window.location. I wasn't sure myself but it's nicely answered here: window.location versus just location

Set input value that has been binded with v-model

I'm creating my own autocomplete feature based on vue.js and materializecss.
https://jsfiddle.net/guanzo/kykubquh/5/
Right now it's working okay, except for a few things.
The normal behavior for an autocomplete is that once you select an item by pressing enter, or clicking, the value of the input becomes your selected item. So if you input "alab", and select the item "Alabama", the value of the input should become "Alabama", and the dropdown list disappears.
The problem is that the input is bound with v-model="query", meaning the value of the input is the value of "query", which is the value of the input.
Trying to change the input value with this.$el.querySelector('input').value = "Alabama" does nothing. My current workaround is to set the value of query to be the value of the selected state.
onSelect(state){
this.selected = state;
this.query = state.name//replace input val
}
A nasty side effect of this is that changing the value of query triggers another search, which causes the dropdown to reappear with the item "Alabama".
How do i change the value of an input that has been bound with v-model?
My attempted workaround is to call this.onBlurInput(); after the user selects an item, which hides the dropdown. However, the dropdown will no longer appear until you explicity refocus the input by clicking outside and back again.
Remove your focus and blur events and add the following line to your queryMatches. You really only want to show options when there is not an exact match.
queryMatches(){
if(this.query.length <= 1){
return [];
}
// check to see if the current value is already in the list
if (this.query === this.selected.name) return [];
console.log(this.query)
var reg = new RegExp(this.query,'gi')
var matches = this.states.filter(state=>{
return reg.test(state.name)
})
console.log(matches)
return matches
}
Here is an updated fiddle.

Dojo EnhancedGrid and programmatic selection

Here's my problem: in my application I have a Dojo EnhancedGrid, backed up by an ItemFileReadStore. The page flow looks like this:
The user selects a value from a selection list.
The item from the list is posted on a server and then the grid is updated with data from the server (don't ask why, this is how it's supposed to work)
The new item is highlighted in the grid.
Now, the first two steps work like a charm; however, the third step gave me some headaches. After the data is successfully POSTed to the server (via dojo.xhrPost() ) the following code runs:
myGrid.store.close();
myGrid._refresh();
myGrid.store.fetch({
onComplete : function(items) {
for ( var i = 0; i < items.length; i++) {
if (items[i].documentType[0].id == documentTypeId) {
var newItemIndex = myGrid.getItemIndex(items[i]);
exportMappingGrid.selection.deselectAll();
exportMappingGrid.selection.addToSelection(newItemIndex);
}
}
}
});
Now, the selection of the grid is updated (i.e. the selection object has a selectedIndex > 0), but visually there's no response, unless I hover the mouse over the "selected" row. If I remove the .deselectAll() line (which I suspected as the culprit) then I sometimes end up with two items selected at once, although the grid selectionMode attribute is set to single.
Any thoughts on this one?
Thanks a lot.
You need to use setSelected(), like so
exportMappingGrid.selection.setSelected(newItemIndex, true);
The second parameter is true to select the row, false to unselect it.
This is what works for me:
grid.selection.clear();
grid.selection.addToSelection(newItemIndex);
grid.selection.getFirstSelected();
Jon

Appending multiple elements in D3

Can anyone explain why a selectAll + data + enter + append works fine initially, but when I call it again it only appends a single element?
http://jsfiddle.net/scottieb/wQJen/
When I run
vis.selectAll("circle")
.data(datafiltered).enter().append("svg:circle")
.attr("cx", function(d) { return x(d.x)})
.attr("cy", function(d) { return y(d.y)})
.attr("fill", "red").attr("r", 15);
I get four points (corresponding to the four pairs of data in 'datafiltered.'). But on button click, I run
vis.selectAll("circle")
.data(datafiltered2)
.enter().append("svg:circle")
.attr("cx", function(d) {
return x(d.x)
}).attr("cy", function(d) {
return y(d.y)
}).attr("fill", "black").attr("r", 5);
and only add the final element of 'datafiltered2' (five pairs in this one). So, the data are different and the second one occurs on button click, but not sure why I'm only getting the one point added!
The issue here is that there is no key function on the data you are binding, so D3 uses the index instead - hence the first four (pre-existing) elements are bound with new data, and the single 5th element gets added.
See this recent tutorial for details on key functions: http://bost.ocks.org/mike/constancy/
Possibly you really only wanted to add the single element, but also change the existing elements to represent their newly bound data, as in: http://jsfiddle.net/jsl6906/wQJen/2/
The result of calling the .enter() method is a set for new elements. Use the original selection for existing elements. See Enter and Exit on the D3 site.
// Update…
var p = d3.select("body").selectAll("p")
.data([4, 8, 15, 16, 23, 42])
.text(String);
// Enter…
p.enter().append("p")
.text(String);
// Exit…
p.exit().remove();