1

I am trying to create a page that grabs a set of PDFs sorted by date. I can't seem to increment the date correctly. I'm not sure what's going wrong here. I rewrote the code twice now. No luck.

The current issue is that the set variables for the date do not keep the value of the date as a whole. IE incrementing from 12, 31, 2018, or in the case of the URL format 20181231, should result urlIncremented=20190101. January 1st, 2019, but the result of my code is urlIncremented=20181232.

The end result of one loop if set to June 8th 2018, should be: url20180608

I've searched for advice on here, and found a JS file called Date.JS; I've imported it and it was looking promising but just consoles out a part of its code, namely:

function () {
   if (this._isSecond) {
        this._isSecond=false;
        return this;
   }
   if (this._same) {
        this._same=this._is=false;
        var o1=this.toObject(),
            o2=(arguments[0] || new Date()).toObject(), 
            v="",
            k=j.toLowerCase();
        for (var m=(px.length-1); m>-1; m--) { 
            v=px[m].toLowerCase();
            if (o1[v]!=o2[v]) { 
                return false;
            }
            if (k==v) { 
                break;
            }
        }
        return true;
   }
   if (j.substring(j.length-1)!="s") { 
       j+="s";
   }
   return this["add"+j](this._orient);
}

Just a heads up I do not yet know jQuery, I was just playing with it to see if it would help..

Here is my actual code.

 let url = "blank",
        firstRun = true;
    
    /* 
    function setDateByIncrement(currentSetDate){
      let newDate,
          currentDate = new Date(),
          day = currentDate.getDate()+1,
          month = currentDate.getMonth() + 1,
          year = currentDate.getFullYear();
    
      console.log(newDate);
      newDate = (year+month+day);
      console.log(newDate);
      return newDate;
    }
    */
    
    // use on First run to set the url and date.
    //3
    function setURL(){
      let urlIncremented = url + dateIncrementMethod();
      return urlIncremented;
    }
    
    // will open x number of new windows containing URL
    //2
    function grabOpenPDF(maxNumberDays){
      let urlSet = setURL();
      
      //Set the variable for max days.
      for(let x = 0; x < maxNumberDays; x++){
        //window.open(urlSet);
        console.log("It works: " + x);
        urlSet = setURL();
      }
    }
    
    /* TODO Add automatic download for MASS print.
    function downloadPDF(){
      
    }
    */
    
    //Starts the task. 
    //1
    function start(load){
      console.log("Current Address: " + url);
      if(load === 1){
        console.log("Event load active. ");
        let maxDay = document.querySelector('#maxNumberDays').value;;
        grabOpenPDF(maxDay);
      }else{
        console.log("Event load skip. ")
        let maxDay = document.getElementById('maxNumberDays').value;
        
      }
    }
    
    //4
    function dateIncrementMethod(current){
      let dateIncrement;
      if(firstRun=== true){
        var today = new Date($('#date-input').val());
        console.log("FirstRun check in 4. ")
      }
      firstRun = false;
      
      var tomorrow = today.add(1).day;
      console.log(tomorrow);
      
      return tomorrow;
    }
      /* Possibly Deprecated  
      //let dateIncrement;
          let date = new Date($('#date-input').val());
          console.log(date);
          day = date.getDate() + 1;
      if(firstRun === true){
          month = date.getMonth() + 1;
          year = date.getFullYear();
          //dateIncrement = (parseToAPI(year, month, day));
          firstRun = false;
          parseToAPI(year, month, day);
        }else{
          day = date.getDate()+1;
          parseToAPI(year, month, day);
        }
    }
    */
    function parseToAPI(year, month, day){
      let apiDate;
      console.log("Entered parse");
      this.day = day;
      this.month = month;
      let d = this.day.toString(),
          m = this.month.toString();
          if(d.length === 1){
            console.log("Entered First IF");
            this.day = ('0') + day;
            //console.log(day);
          }
          if(m.length === 1){
            console.log("Entered Second IF")
            this.month = ('0') + month;
          }
      apiDate = (year + "" + "" + month + "" + day);
      console.log(apiDate);
      return apiDate;
    }
<!DOCTYPE html>
<html>
<script src="https://code.jquery.com/jquery-2.0.3.js"></script>
<script src="https://doc-0k-6g-docs.googleusercontent.com/docs/securesc/77gdpvi38k94jj7nmfcm2n3tq7a0ifhu/ehjuusajghqnne5r2ncfvj30cmbll20p/1545105600000/17500114768188980350/17500114768188980350/1CDff-uWGahZX7aLt6WQfV1-R5PFHwiK8?e=download&nonce=52qkphatg2scm&user=17500114768188980350&hash=3uc9iql9m90vcrv3a7mhg8fdjce1b4fe.js"></script>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width">
    <title>JS Bin</title>
</head>
<body>
    <input type="date" id="date-input" required />
        <input type="maxNumberDays" id="maxNumberDays" max="31" required />
        <button id="startPDFApp" onClick="start()">Print PDFs</button>
        <button id="startPDFApp" onClick="start(1)">Load PDFs</button>
        <div id="info"></div>
    </body>
</html>
halfer
  • 19,824
  • 17
  • 99
  • 186
  • Do you want a jQuery solution? You may consider also using jQuery UI for it's datepicker as it can return a Date object and make life a bit easier for this. I think I see where you're aiming for `tomorrow` and I am guessing as long as `tomorrow is before or the maxDate, it will keep looping. Am I following right? – Twisty Dec 18 '18 at 06:01
  • I do need to learn jQuery,.. so if in a novice explanation, yes please. I can look into datepicker, at some point tomorrow. In short yes you are correct. But more so, the maxNumberDays is set to kill the loop after a certain amount of days. The end result of this task depending on the button used, should leave the user with a load of new tabs with the relevant URL. – LiveBacteria Dec 18 '18 at 06:07
  • Maybe include some instructions on how to fill it out to reproduce whatever you're doing and what the desired behavior should be? – vol7ron Dec 18 '18 at 06:08
  • Added a bit more detail, the code is not finished I'm just looking for a way to consistently increment the date from a preset value. – LiveBacteria Dec 18 '18 at 06:15
  • Here's a missing piece: `tomorrow = new Date(today); tomorrow.setDate( tomorrow.getDate() + 1);` and you don't need jQuery here – vol7ron Dec 18 '18 at 06:21
  • Error in Tomorrow.getDate is not a function. – LiveBacteria Dec 18 '18 at 06:35
  • Please see [*How to create a minimal, complete and verifiable example*](https://stackoverflow.com/help/mcve). There is a lot of code that doesn't need to be in the post. – RobG Dec 18 '18 at 06:44
  • @LiveBacteria check your spelling, it looks like you may have capitalized something you didn't need to ;) also see my *answer* below for more further help – vol7ron Dec 18 '18 at 07:08

3 Answers3

1

While I haven't invested enough time trying to understand what you're really trying to do, it seems like there's a lot of unnecessary code. I'll leave it to you to decipher what you need.

I can only express that the below code is in an in-between state. It includes a number of changes, most of which I'll point out, but I didn't want to change it too drastically that it all looked foreign. So even the code below has much to be improved on.

Significant changes include:

  1. Because your URL is increasing by one, you may benefit by using a function generator. Inside it increases the date by calling setDate on itself using it's own date + 1. It also uses a string function, padStart, to ensure months and days are always two-digit.

  2. Getting rid of firstRun variable as it is no longer needed

  3. Inside your grabOpenPDF, all you need to do is get the next value returned by the URL generator function

let URL_GEN = UrlGenerator('blank'),
  URL = URL_GEN.next().value;


//Starts the task. 
//1
function start(load) {
  let startDate = new Date(document.querySelector('#date-input').value)
  
  // overwrite global with values
  URL_GEN = UrlGenerator('blank', startDate)
  URL = URL_GEN.next().value
  
  console.log("Current Address: " + URL);
  if (load === 1) {
    console.log("Event load active.");
    let maxDay = document.querySelector('#maxNumberDays').value;
    grabOpenPDF(maxDay);
  } else {
    console.log("Event load skip.")
    let maxDay = document.getElementById('maxNumberDays').value;
  }
}

/* URL generator */
function* UrlGenerator(url, dt=new Date()) {
  while (true){
    yield url + dt.getFullYear() + (''+(dt.getMonth()+1)).padStart(2,'0') + (''+dt.getDate()).padStart(2,'0');
    
    // increase day for next iteration
    dt.setDate(dt.getDate()+1);
  }
}


// will open x number of new windows containing URL
function grabOpenPDF(maxNumberDays) {

  //Set the variable for max days.
  for (let i=0; i < maxNumberDays; i++) {
    console.log("It works: " + i, URL);
    URL = URL_GEN.next().value;
  }
}
<script src="https://doc-0k-6g-docs.googleusercontent.com/docs/securesc/77gdpvi38k94jj7nmfcm2n3tq7a0ifhu/ehjuusajghqnne5r2ncfvj30cmbll20p/1545105600000/17500114768188980350/17500114768188980350/1CDff-uWGahZX7aLt6WQfV1-R5PFHwiK8?e=download&nonce=52qkphatg2scm&user=17500114768188980350&hash=3uc9iql9m90vcrv3a7mhg8fdjce1b4fe.js"></script>
<input type="date" id="date-input" value="12/29/2018" required />
<input type="maxNumberDays" id="maxNumberDays" value="5" max="31" required />
<button id="startPDFApp" onClick="start()">Print PDFs</button>
<button id="startPDFApp" onClick="start(1)">Load PDFs</button>
<div id="info"></div>

This can be further improved by better management of your globals, more straightforward code (more simply laid out), and perhaps better naming conventions. Also, it's generally a no-no to be putting event handlers directly in the HTML these days, you could bind those event dynamically via JavaScript.

vol7ron
  • 40,809
  • 21
  • 119
  • 172
  • Wow, thank you a lot. Finally someome who doesn't just give out an answer. I will take your help and make myself better with it. – LiveBacteria Dec 18 '18 at 07:13
  • I have alot to learn. Yield looks very useful. The function then asterisk is the only thing im thing up on atm. – LiveBacteria Dec 18 '18 at 07:19
  • 1
    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator#Example – vol7ron Dec 18 '18 at 07:24
  • Turns out its a generator function, this is so cool. Also, I put the event onClick in html because when i was mocking it up, it was the fastest way I knew how. – LiveBacteria Dec 18 '18 at 07:27
0

I can't seem to increment the date correctly.

If you have a dates like "20181231" with a format YYYYMMDD, you must parse it to the date parts, increment the day, then format it back to an appropriate string. A date manipulation library can help, or you can write a custom function.

You can do it without generating a Date, but it's a bit more code and logic.

E.g.

// Accept date string in format YYYYMMDD
// and return next date in same format
function getNextDate(s) {
  let z = n => ('0'+n).slice(-2);
  let [y, m, d] = s.match(/^\d{4}|\d{2}/g);
  let date = new Date(y, m-1, d);
  date.setDate(date.getDate() + 1);
  return date.getFullYear() + z(date.getMonth()+1) + z(date.getDate());
}

['20181230','20181231','20190101'].forEach(
  s => console.log(`${s} => ${getNextDate(s)}`)
);

You can also use a library like moment.js:

function getNextDate(s) {
  return moment(s, 'YYYYMMDD')
           .add(1, 'day')
           .format('YYYYMMDD');
}



['20181230','20181231','20190101'].forEach(
  s => console.log(`${s} => ${getNextDate(s)}`)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.min.js"></script>

If you are using moment.js for other things, include it. But if this is the only date stuff you need it for, it's a bit of overhead you don't need.

RobG
  • 142,382
  • 31
  • 172
  • 209
  • Thanks for the help and concepts here. Im working on my arrow finctions still, so its slowing me down comprehending your code. Moment.js looks amazing for the simple task. But so did date.js. I'll try this out as well. – LiveBacteria Dec 18 '18 at 07:30
0

A lot of your code is a little unclear and the logic is not obvious, in regards to what should happen. Here is what I could gleam:

  1. User should enter a Date, that is required
  2. When user click Load PDF, a list of dates should be calculated
    • Assuming today until selected date, with a max of 31 days in the future
  3. The script checks if a PDF exists for each of the days in the list

I suspect you were just looking for a way to generate a pattern for the days. I may have more here than you need.

$(function() {
  function grabOpenPDF(end) {
    var current = new Date();
    end.setDate(end.getDate() + 1);
    var urls = [];
    while (current < end) {
      urls.push({
        name: $.datepicker.formatDate("yymmdd", current),
        url: "https://example.com/getpdf.php?date=" + $.datepicker.formatDate("yymmdd", current),
        hit: null
      });
      current.setDate(current.getDate() + 1);
    };
    console.log(urls);
    $.each(urls, function(k, v) {
      $.ajax({
        url: v.url,
        success: function(data) {
          v.hit = true;
          $("#info").append("<div>" + (k + 1) + ". " + v.url + ", hit: " + v.hit.toString() + "</div>");
        },
        error: function(data) {
          v.hit = false;
          $("#info").append("<div>" + (k + 1) + ". " + v.url + ", hit: " + v.hit.toString() + "</div>");
        }
      });
    });
  }

  var dtInp = $("#date-input").datepicker({
    dateFormat: "mm/dd/yy",
    maxDate: "+31d",
    minDate: new Date()
  });
  $(".today").html($.datepicker.formatDate("mm/dd/yy", new Date()));
  $("#printPDF").click();
  $("#startPDF").click(function(e) {
    e.preventDefault();
    $("#info").html("");
    if ($("#date-input").val() === "") {
      $("#date-input").focus();
      return false;
    }
    console.log("Event load active.");
    grabOpenPDF(dtInp.datepicker("getDate"));
  });
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script src="https://doc-0k-6g-docs.googleusercontent.com/docs/securesc/77gdpvi38k94jj7nmfcm2n3tq7a0ifhu/ehjuusajghqnne5r2ncfvj30cmbll20p/1545105600000/17500114768188980350/17500114768188980350/1CDff-uWGahZX7aLt6WQfV1-R5PFHwiK8?e=download&nonce=52qkphatg2scm&user=17500114768188980350&hash=3uc9iql9m90vcrv3a7mhg8fdjce1b4fe.js"></script>

<div class="ui-widget ui-widget-content" style="padding: 7px;">
  <p>From <span class="today">Today</span> until <input type="text" id="date-input" placeholder="mm/dd/yy" required style="border: 0; width: 8em; border-radius: 0; border-bottom: 1px solid #eee;" /></p>
  <button id="printPDF">Print PDFs</button>
  <button id="startPDF">Load PDFs</button>
  <div id="info"></div>
</div>

As I mentioned, you can use jQuery and jQuery UI to help you out. Take a look: http://api.jqueryui.com/datepicker/

When the user clicks on the field, they can select a date between today and 31 days into the future. they can then click the "Load PDF" button and it will grab the PDFs by iterating each day and performing some action.

Good reference for incrementing the date: Incrementing a date in JavaScript

Personally, I would push this off to the server instead of doing this in the browser. Assuming there is a DB of PDFs, it would be faster to send a start and end date to the server and have it perform a SELECT query and return the results. You're sending two bits of data to the server and getting a list of results versus hammering around for PDFs hoping to find your nail. using the above example, you could set the option, minDate: "-6m" and just limit the range the user might select a start and end date.

Hope this helps. Feel free to comment and ask for more clarity if needed.

Twisty
  • 30,304
  • 2
  • 26
  • 45