Javascript with a for in loop - for-in-loop

working on the follow code. Having some issues with taking the user input from the day and the temp. I have a start but again running into an issue with Step 2 & 3 unable to pass the information to the array and figure out how to display it. Any insight and direction would be greatly appreciated. Thanks
var temperatures = [];
var days = ["Monday", "Tuesday","Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
var $ = function (id) {
return document.getElementById(id);
}
var takeTemps = function () {
//###STEP 2
//Get the user inputted temp, validate it making sure it's a number
//if it's valid add it to the temperatures array at the index that
// corresponds with the day of week, e.g. 0 for Monday, 2 for Wednesday
var userTemp=(parseFloat($("tempIn").value));
while (!isNaN(tempIn)==true)
{
alert("Please enter a numeric value");
$("tempIn").focus();
}
//This gets the value from the selected menu option
var index = $("daySelect").value;
for(var dayTemp in temperatures)
{
var daily=temperatures[index]
}
//remove this when done, this just tests your menu you wrote for step 1
alert( index + " indexes day " + days[index]+ userTemp);
//Call displayTemps ONLY if the temp input was valid.
displayTemps();
//EXTRA work / not credit
// have it auto advance the selected day in the menu
// by assigning into $("daySelect").value
// If it was on Sunday change it to Monday and only on valid input
}
var displayTemps = function () {
//###STEP 3
//loop through non-undefined indexes in the temperatures array
//appended them to tempString adding the day .e.x
//Tuesday: 89
//Friday: 98
//display the string to the page by setting the value of the textarea
//
//In the same loop sum the temperatures and count
// how many there are so you can calculate the average
// and output the average temp on the page.
tempString = "";
tempTemp = 0;
for(var i in temperatures) {
tempString += index + ": " + temperatures[i];
}
document.write(tempString + "<br>");
var average =tempTemp+10;
$("tempList").value=tempString;
$("avgOut").value=average;
}
window.onload = function () {
$("addTemp").onclick = takeTemps;
//###STEP 1
//Use a for loop here to write options to the select for each day of the week
// <option value="0">Monday</option>
// using += here with innerHTML property takes the existing values and concats this on the end
for (var i =0; i<7; i++)
{
$("daySelect").innerHTML += "<option value=\""+ i + "\">" + days[i] + "</option>\n";
$("daySelect").value = "";
//var day=i-1;
//var day = days[i];
}
$("tempIn").focus();
}
Struggles with Step 2 and 3 Beleive i have #1 good to go I have enclosed the HTML for reference
<html>
<head>
<script src=script.js></script>
<head>
<body>
<section>
<select id="daySelect">
<option value="">Select a day</option>
</select>
<input type="text" id="tempIn">
<input type="button" id="addTemp" value="add temperature">
<br>
<br>
<label for="tempList">Temperature List</label>
<br>
<textarea id="tempList" rows="7" cols="50"></textarea>
<br>
<label>Average Temperature</label>
<input type="text" id="avgOut" disabled>
</section>
</body></html>

I would suggest to provide more specific information about which part of the code you are concerned with, and especially, provide the HTML code as well since that would enable us to see more clearly what you are trying to do.
When you are done, I will edit this answer and you will get appropriate guidance.
Keep coding!
EDIT
Take a look:
var userTemp=(parseFloat($("tempIn").value));
while (!isNaN(tempIn)==true)
{
alert("Please enter a numeric value");
$("tempIn").focus();
}
Looking at this little piece of code from "Step 2", I can think of a number of bugs already. Of course I'm not sure since I haven't seen your HTML yet, but it seems like:
You have put the value of the input into a variable named userTemp, yet you are checking for a variable named "tempIn" for validation. The second one probably doesn't exist at that point in time. "tempIn" was the name of your DOM element, not the JS variable you've assigned its value. You have to check for the userTemp variable.
In your validation, you are checking for the opposite of isNaN. NaN means "Not a Number", so the opposite of that would be actually number, so the statement is wrong. Not to mention that in this, you would not need to explicitly express "==true", you can check like this: while(isNaN(userTemp))
If you want to iterate a while statement for validation until you get a valid number, you need to put the variable assignment inside the while statement, since you'll need to try to assign the new number each time the validation loop iterates.
EDIT 2 - finished
Your code is live here:
https://codepen.io/bradib0y/pen/OBEdvp?editors=1010
Please note that if you are working your way through a course and this was your assessment, you've gained exactly nothing with me making these tasks for you. You will only gain from getting throught these challenges yourself.
I suggest to spend at least 1 hour with analyzing this code step by step and try to replicate it in a similar project. If you still have struggle with understanding, do yourself a favor and start over with basic javascript once again. You will be an expert on this within a week, if you put the basics down right. But if you still can't grasp the basics and keep pushing forward with more complex issues, you will have a hard time.

Related

Shopify: how to retrieve shop level metafield in the cartpage?

At a shop level, I created a metafield for disabled dates as shown in the image below, that I want to retrieve and assign to a LIQUID variable in the code following the image.
Code in cart page:
window.addEventListener("load", function() {
// Don't add 0 before month and date to make it two digit.
//var disabledDays = ["2022-5-30","2022-7-4","2022-9-5","2022-11-24","2022-12-23","2022-12-24","2022-12-25","2022-12-30","2022-12-31","2023-1-1","2023-1-2"];
disabledDays = {{ shop.metafields.disabledDays.value }};
var minDate = new Date();
var maxDate = new Date();
maxDate.setDate((maxDate.getDate()) + 60);
minDaysToShip = 2; // Default minimum days
if (minDate.getDay() == 5) {
// Friday. Set min day to Tuesday. 4 days from now.
minDaysToShip = 4;
} else if (minDate.getDay() == 6) {
I see that {{ shop.metafields.disabledDates.value }}; is not reading the metadata content. Please show me the right way to do it.
If you are in a .liquid file, the following syntax should work for string type metafields:
{{ shop.metafields.disabledDays.disabledDays }}
Shopify added more metafield types and the new ones can indeed be accessed through the .value key, see this thread for more details:
https://community.shopify.com/c/technical-q-a/how-to-access-json-data-from-the-new-shopify-native-metafields/td-p/1258088

SSIS Import data that is NOT columnar into SQL

I am fairly new to SSIS and need a little help getting started. I have several reports that come out of our mainframe. The reports are not in a columnar format. The date record is at the top then there might be some initial data then there might be a little more. So I need to read in each line look to see what the text reads and figure out if I need the data or move to the next row.
This is a VERY rough example of what the report I want to import into a SQL table.
DATE: 01/08/2020 FACILITY NAME PAGE1
REVENUE USAGE FOR ACCOUNTING PERIOD 02
----TOTAL---- ----TOTAL---- ----OTHER---- ----INSURANCE---- ----INSURANCE2----
SERVICE CODE - 123456789 DESCRIPTION: WIDGETS
CURR 2,077
IP 0.0000 3 2,345 0.00
143
OP 0.0000 2 1,231 0.00
YTD 5
IP 0.0000
76
OP 0.0000
etc . . . .. .
SERVICE CODE
After the SERVICE CODE the data will start to repeat like it is above. This is the basic idea of a report.
I want to get the Date then the Service Code, Description, Current IP Volume, Current IP Dollar, Current OP Volume, Current OP Dollar, YTD IP Volume, YTD IP Dollar, YTD OP Volume, YTD OP Dollar . . then repeat.
Just to clarify, I am not asking anyone to do this for me. I want to learn how to do this. I have looked on how to do this but every example I have looked at talks about doing this with a CSV, tab, or Excel file. i do not have that type of file so I was asking what I need to look at. I currently use Monarch to format the file, but again I want to learn more about SSIS and this is a perfect way to learn. Asking the vendor to redo the report is not an option plus I want to learn how to do this. Thank you I just wanted to get that out there.
Any help would be greatly appreciated.
Rodger
As stated in comments, you could do this using a script task. The basics steps are:
Define a DataTable to store your data.
Use a StreamReader to read your report.
Process this using a combination of conditionals, String Methods, and parsing to extract the relevant fields from the relevant line:
Write the DataTable to the database using SqlBulkCopy
The following would go inside your Main method in your script task:
//Define a table to store your data
var table = new DataTable
{
Columns =
{
{ "ServiceCode", typeof(string) },
{ "Description", typeof(string) },
{ "CurrentIPVolume", typeof(int) },
{ "CurrentIPDollar,", typeof(decimal) },
{ "CurrentOPVolume", typeof(int) },
{ "CurrentOPDollar", typeof(decimal) },
{ "YTDIPVolume", typeof(int) },
{ "YTDIPDollar,", typeof(decimal) },
{ "YTDOPVolume", typeof(int) },
{ "YTDOPDollar", typeof(decimal) }
}
};
var filePath = #"Your File Path";
using (var reader = new StreamReader(filePath))
{
string line = null;
DataRow row = null;
// As YTD and Curr are identical, we will need a flag later to mark our position within the record
bool ytdFlag= false;
//Loop through every line in the file
while ((line = reader.ReadLine()) != null)
{
//if the line is blank, move on to the next
if (string.IsNullOrWhiteSpace(line)
continue;
// If the line starts with service code, then it marks the start of a new record
if (line.StartsWith("SERVICE CODE"))
{
//If the current value for row is not null then this is
//not the first record, so we need to add the previous
//record to the tale before continuing
if (row != null)
{
table.Rows.Add(row);
ytdFlag= false; // New record, reset YTD flag
}
row = table.NewRow();
//Split the line now based on known values:
var tokens = line.Split(new string[] { "SERVICE CODE - ", "DESCRIPTION: "}, StringSplitOptions.None);
row[0] = tokens[0];
row[1] = tokens[1];
}
if (line.StartsWith("CURR"))
{
//Process the row --> "CURR 2,077"
//Not sure what 2,077 is, but this will parse it
int i = 0;
if (int.TryParse(line.Substring(4).Trim().Replace(",", ""), out i))
{
//Do something with your int
Console.WriteLine(i);
}
}
if (line.StartsWith(" IP"))
{
//Start at after IP then split the line into the 4 numbers
var tokens = line.Substring(3).Split(new [] { " "}, StringSplitOptions.RemoveEmptyEntries);
//If we have gone past the CURR record, then at to YTD Columns
if (ytdFlag)
{
row[6] = int.Parse(tokens[1]);
row[7] = decimal.Parse(tokens[1]);
}
//Otherwise we are still in the CURR section:
else
{
row[2] = int.Parse(tokens[1]);
row[3] = decimal.Parse(tokens[1]);
}
}
if (line.StartsWith(" OP"))
{
//Start at after OP then split the line into the 4 numbers
var tokens = line.Substring(3).Split(new [] { " "}, StringSplitOptions.RemoveEmptyEntries);
//If we have gone past the CURR record, then at to YTD Columns
if (ytdFlag)
{
row[8] = int.Parse(tokens[1]);
row[9] = decimal.Parse(tokens[1]);
}
//Otherwise we are still in the CURR section:
else
{
row[4] = int.Parse(tokens[1]);
row[5] = decimal.Parse(tokens[1]);
}
//After we have processed an OP record, we must set the YTD Flag to true.
//Doesn't matter if it is the YTD OP record, since the flag will be reset
//By the next line that starts with SERVICE CODE anyway
ytdFlag= true;
}
}
}
//Now that we have processed the file, we can write the data to a database
using (var sqlBulkCopy = new SqlBulkCopy("Your Connection String"))
{
sqlBulkCopy.DestinationTableName = "dbo.YourTable";
//If necessary add column mappings, but if your DataTable matches your database table
//then this is not required
sqlBulkCopy.WriteToServer(table);
}
This is a very quick example, far from the finished article, and I have done little or no testing, but it should give you the gist of how it could be done, and get you started on one possible solution.
It can definitely be cleaned up and refactored, but I have tried to make it as clear as possible what is going on, rather than trying to write the most efficient code ever. It should also (hopefully) demonstrate what a monumental pain this is to do, and very minor report changes things like an extra space be "OP" will break the whole thing.
So again, I would re-iterate, if you can get the data in a standard flat file format, with one line per record, you should. I do however appreciate that sometimes these things are out of your control, and I have had to write incredibly ugly import routines like this in the past, so I feel your pain if you can't get the data in a consumable format.

Vue.js: error setting a computed property

in the following code (jsbin available here) I have two input elements, a range and a text, bound together via a computed property.
var vm = new Vue({
el: '#main-container',
data: {
sliderValue: 100,
},
computed: {
actualValue: {
get: function() {
if (this.sliderValue <= 100) {
return this.sliderValue;
} else {
return Math.round(this.sliderValue * 12.5 - 1150);
}
},
/* set won't work for val > 100*/
set: function(val) {
if (val <= 100) {
this.sliderValue = val;
} else {
this.sliderValue = Math.round((val + 1150)/12.5);
}
}
}
},
methods: {
}
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.0.3/vue.js"></script>
<div id="main-container">
<input type="range" v-model="sliderValue" min=1 max=132>
<input type="text" v-model="actualValue">
<p>Slider: {{sliderValue}}</p>
<p>Actual: {{actualValue}}</p>
</div>
The range goes from 1 to 132, and its range is mapped [1..500] in the text input, with a simple transformation (basically it's a linear mapping with two different slopes for [1..100] and [101..132]) using the actualValue computed property.
Getting actualValue works as expected: dragging the slider correctly updates the input text with appropriate values in the range [1..500].
I'm not able to find a way to set actualValue, though. I'd like to be able to type a value in the text input, and make the slider's thumb update accordingly to the inverse transformation (val + 1150)/12.5.
It works as long as the typed number is in the range [1..100], but it "explodes" for numbers >100, e.g. 101 makes the sliderValue jump at 80892 and actualValue is then re-calculated as 1010000. As far as I understand, it's a looping-feedback scenario.
I've tried also alternative approaches (watch; v-on:change in the text input; using a third variable) to no avail.
Thanks in advance for any suggestion!
It's an amazing puzzle, and challenged me for a long time!
Look at the screenshot below. Your sliderValue and actualValue are strings, not integers. When you set actualValue as 101, you are actually setting it as a string value of "101"
Now, your sliderValue = ((actualValue + 1150)/12.5)
"101" + 1150 = "1011150" (another string!, try it in the developer console)
That messes up your entire calculation. Now you know how to fix it :-)
And you need to get that Vue devtools from here: https://github.com/vuejs/vue-devtools
EDIT: Response to comment #3
Here is the modified jsBin: http://jsbin.com/mahejozeye/1/edit?html,js,output
The only difference is introduction of two console.log statements in your map2 function. This helps you identify if your non-linear mapping function is working correctly or not. If you keep your developer console open, you will see what is happening in this function.
Case 1: When you set the value radius = 25 using the text box, your sliderRadius gets set to 111.55518394648828 and your radius again gets re-calculated as 25. So it comes around in a full circle and everything is stable here.
Case 2: When you set the value radius = 55, your sliderRadius gets set to 173.03607214428857 through your non-linear map2() function, which resets radius to 51.29869180420927
Clearly there is a circular dependency issue. Your sliderRadius and radius are very much dependent on each other and therefore radius is unable to take the value between 51 and 58.
You need to evaluate why it happens, as it has a lot to do with the non-linear mapping function that you have defined. The moment radius can take stable values at 55 (through the map2 function), then your current problem will be resolved.
The simplest fix is to set your input type to number:
<input type="number" v-model="actualValue">
or you can convert your value to an integer with something like:
set: function(val) {
var intVal = parseInt(val, 10);
if (!isNaN(intVal)) {
if (intVal <= 100) {
this.sliderValue = Math.max(1, intVal);
} else {
this.sliderValue = Math.min(132, Math.round((intVal + 1150) / 12.5));
}
}
}

handlebars returning index along with data

I have a helper that loops through jason data till a given value and sends the data back to the template.I also want to show at what location the data is present (the index), is there any way where in i can return the Index value along with the data?
Handlebars.registerHelper('print_range', function(items,count,options)
{
var out = "";
for(var i=0, l=items.length; i<count; i++)
{
out = out + options.fn(items[i]);
}
return out;
});
<script id="template" type="text/x-handlebars-template">
{{#print_range options "2"}}
<h1>index</h1> // this index should correspond to i in the helper function
<h2>{{optionID}}{{nextID}}</h2>
{{/print_range}}
</script>
Thanks in advance.
Handlebars.registerHelper('print_range', function(items,count,options)
{{#print_range options "2"}}
Not sure 100% what you're asking, but i do see a problem in your code. You specify 3 parameters in the function, but only give it 2 in your statement call to the helper.
{{#print_range options "2"}}
^ fn name ^items ^ count
Where's the value for your options variable? In handlebars, the parameters for the function go in order after the helper name you are calling

YUI Datatable - Get ID of DOM Element after page has loaded and use it in other YUI events

Okay so I have a YUI Datatable. Most of it is exactly as the how to guide says to construct it.
I have an event that governs changing the rows per page. It's linked to the rows per page drop down element and it saves the value of that drop down as a cookie when the drop down is changed.
var onRPPChange1 = YAHOO.util.Event.addListener("yui-pg0-1-rpp24", "change", getRPP_1);
The problem is that "yui-pg0-1-rpp24" (the ID of the drop down) changes whenever I make updates to my data table. I would like to extend this so that when the page loads it will dynamically insert the ID of that drop down into this event listener so that I don't have to keep editing it after future updates.
I've managed to construct that following that will capture the ID and I can alert it after the table loads, but so far, including the result of this function in the above addListener code isn't working.
var setRPPVars = function() {
YAHOO.util.Event.onAvailable("rppSpan", this.handleOnAvailable, this);
}
var rppSpanIds = new Array();
var rppArray = new Array();
setRPPVars.prototype.handleOnAvailable = function() {
var spans = document.getElementsByTagName("span");
var n = 0;
for(var i=0; i<spans.length; i++){
if(spans[i].id == "rppSpan"){
rppSpanIds[n] = spans[i];
if(n == 0){
rppTopID = rppSpanIds[n].firstChild.id;
rppArray[0] = rppTopID;
}
else if(n==1){
rppBottomID = rppSpanIds[n].firstChild.id;
rppArray[1] = rppBottomID;
}
n++;
}
}
alert(rppTopID);
alert(rppBottomID);
alert(rppArray);
}
var rppEvent = new setRPPVars();
//this is the part that doesn't work:
var onRPPChange0 = YAHOO.util.Event.addListener(rppArray[0], "onchange", getRPP_0);
function getRPP_0(){setRPPVars();oRPP = rppTopID;alert("rppTopID: "+rppTopID); alert("oRPP: "+oRPP);};
Any suggestions you've got would be awesome!
EDIT: For clarity's sake, this element is the rows per page drop down:
<span id="rppSpan">
<select id="yui-pg0-1-rpp24" class="yui-pg-rpp-options" title="Rows per page">
<option value="10">10</option>
<option value="25">25</option>
<option value="50">50</option>
<option value="100">100</option>
</select>
</span>
Subscribe to YAHOO.widget.Paginator's rowsPerPageChange instead:
http://developer.yahoo.com/yui/docs/YAHOO.widget.Paginator.html#event_rowsPerPageChange
Then you don't have to find the actual element.