Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save bbarman4u/d6c337572b476af14a313e40d63a2e84 to your computer and use it in GitHub Desktop.

Select an option

Save bbarman4u/d6c337572b476af14a313e40d63a2e84 to your computer and use it in GitHub Desktop.

Revisions

  1. @medinm0 medinm0 revised this gist Jul 3, 2019. 1 changed file with 9 additions and 2 deletions.
    11 changes: 9 additions & 2 deletions southwest_auto_checkin.user.js
    Original file line number Diff line number Diff line change
    @@ -1,11 +1,12 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace https://gist.github.com/ryanizzo/058829a5fafe733bd876410db7a1e699
    // @version 1.9
    // @version 1.91
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    // @contributor Trevor McClellan (github.com/trevormcclellan)
    // @contributor Martin Medina (github.com/medinm0)
    // @description Automatically check in to Southwest Airline flights at the appropriate time.
    // @include https://www.southwest.com/air/check-in/index.html*
    // @include https://www.southwest.com/flight/selectCheckinDocDelivery.html*
    @@ -67,6 +68,9 @@
    2/19/2019 v1.9 Shivang Patel (@shivangp)
    - Added interval to continously click submit button after timer is done, in case time is not perfect
    7/3/2019 v1.91 Martin Medina (@medinm0)
    - Fixed endless looping alert on Check In page
    TODO: Use Southwest's server's time instead of the client's clock.
    TODO: Test select passenger page.
    @@ -112,7 +116,10 @@ function submitNow()
    submitButton.click();
    }
    catch(e){
    alert('submitNow: An error has occurred: '+ e.message);
    //stop attempting to submitNow if there is an error preventing endless alert loop
    window.clearInterval(submitNowInterval);
    //alert('submitNow: An error has occurred: '+ e.message);

    }
    }

  2. @shivangp shivangp revised this gist Feb 19, 2019. 1 changed file with 13 additions and 10 deletions.
    23 changes: 13 additions & 10 deletions southwest_auto_checkin.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace https://gist.github.com/ryanizzo/058829a5fafe733bd876410db7a1e699
    // @version 1.8
    // @version 1.9
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    @@ -64,6 +64,9 @@
    - clear displayCountdown interval so does not cause error on other pages
    - removed timeout setTime for displayCountdownWrapper and just called directly
    2/19/2019 v1.9 Shivang Patel (@shivangp)
    - Added interval to continously click submit button after timer is done, in case time is not perfect
    TODO: Use Southwest's server's time instead of the client's clock.
    TODO: Test select passenger page.
    @@ -98,7 +101,7 @@ const REVIEW_SUBMIT_BUTTON_CLASS = "actionable actionable_button actionable_larg
    var globalDisplayCountdownInterval;
    var globalSubmitDate;
    //var allDone = false;

    var submitNowInterval;
    /**
    * @brief Submit the check in form on the Southwest Check In Online page.
    */
    @@ -113,7 +116,6 @@ function submitNow()
    }
    }


    /**
    * @brief Display the countdown.
    *
    @@ -262,7 +264,10 @@ function beginDelay()
    if(errors.length == 0){

    //Install the timeout to submit the form.
    window.setTimeout(submitNow, msRemaining);
    window.setTimeout(function() {
    submitNow();
    submitNowInterval = window.setInterval(submitNow, 500);
    }, msRemaining);

    globalSubmitDate = submitDate;

    @@ -548,14 +553,12 @@ function waitForSendButton() {
    }*/

    //case of the select boarding pass page (regex match the url)
    if(/review/.test(document.location.href))
    {
    autoPassengerPage();
    }
    //case of the check in page
    else if(/index/.test(document.location.href))
    if(/check-in/.test(document.location.href))
    {
    checkInPageFormEdit();
    } else {
    window.clearInterval(submitNowInterval);
    alert("interval cleared");
    }
    /*else if(/confirmation/.test(document.location.href))
    {
  3. @shivangp shivangp revised this gist Feb 2, 2018. 1 changed file with 77 additions and 66 deletions.
    143 changes: 77 additions & 66 deletions southwest_auto_checkin.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace https://gist.github.com/ryanizzo/058829a5fafe733bd876410db7a1e699
    // @version 1.7
    // @version 1.8
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    @@ -58,6 +58,13 @@
    - Commenting out confirmation page for texting boarding pass as this doesnt appear to be fully working.
    - Using single input for date and time
    2/2/2018 v1.8 Shivang Patel (@shivangp)
    - Fixed autoPassengerPage function - now does not have check box and only checkin button
    - changed default auto set time to :05 seconds - :02 seems to early
    - clear displayCountdown interval so does not cause error on other pages
    - removed timeout setTime for displayCountdownWrapper and just called directly
    TODO: Use Southwest's server's time instead of the client's clock.
    TODO: Test select passenger page.
    */
    @@ -88,7 +95,7 @@ const REVIEW_SUBMIT_BUTTON_CLASS = "actionable actionable_button actionable_larg
    //const CONF_TEXT_ID = "textBoardingPass";

    ///////////// CHECK IN PAGE ////////////////

    var globalDisplayCountdownInterval;
    var globalSubmitDate;
    //var allDone = false;

    @@ -123,38 +130,41 @@ function displayCountdown()
    var minutes = Math.floor(timeRemain / (1000 * 60)) % 60;
    //round to the nearest second
    var seconds = Math.round(timeRemain / 1000) % 60;

    //Don't print negative time.
    if (hours < 0 || minutes < 0 || seconds < 0)
    {
    countdown.nodeValue = "Checking In...";
    countdown.nodeValue = "Checking In...";
    return;
    }

    var time = '';
    //If 0 days remain, omit them.
    if (days !== 0)
    time += days + "d ";
    time += days + "d ";
    //If 0 hours remain, omit them.
    if (hours !== 0)
    time += hours + "h ";
    time += hours + "h ";
    //Add padding to minute
    if (minutes !==0 )
    //area.innerHTML += "0";
    time += minutes + "m ";
    //area.innerHTML += "0";
    time += minutes + "m ";
    //Add padding to second
    //if (seconds < 10)
    //area.innerHTML += "0";
    time += seconds;
    time += "s";

    countdown.textContent = time;

    }
    catch(e){
    // has the page changed?
    if(/review/.test(document.location.href))
    {
    /* clear the display countdown interval - otherwise will get error when trying to update */
    clearInterval(globalDisplayCountdownInterval);

    autoPassengerPage();
    return;
    }
    @@ -166,7 +176,7 @@ function displayCountdown()
    }
    return;
    }*/

    alert('displayCountdown: An error has occurred: ' +e.message);
    }
    }
    @@ -178,7 +188,7 @@ function displayCountdown()
    function displayCountdownWrapper()
    {
    try{
    window.setInterval(displayCountdown, 1000);
    globalDisplayCountdownInterval = window.setInterval(displayCountdown, 1000);
    }
    catch(e){
    alert('displayCountdownWrapper:" An error has occurred: ' +e.message);
    @@ -197,48 +207,48 @@ function beginDelay()
    var lastName = document.getElementById(CHECKIN_LASTNAME_INPUT_ID).value;

    var date = document.getElementById("date-input").value;

    var time = document.getElementById("time-input").value;

    // var phoneArea = document.getElementById("phoneArea").value;
    // var phonePrefix = document.getElementById("phonePrefix").value;
    // var phoneNumber = document.getElementById("phoneNumber").value;
    // var phoneArea = document.getElementById("phoneArea").value;
    // var phonePrefix = document.getElementById("phonePrefix").value;
    // var phoneNumber = document.getElementById("phoneNumber").value;

    var errors = "";
    if(confNumber === "" || firstName === "" || lastName === "" )
    errors += "- Must fill out Confirmation Number, First Name and Last Name.\r";
    errors += "- Must fill out Confirmation Number, First Name and Last Name.\r";

    if(confNumber.length != 6 )
    errors += "- Confirmation Number must be 6 characters.\r";
    errors += "- Confirmation Number must be 6 characters.\r";

    if(!isValidDate(date))
    errors += "- Date is not valid.\r";
    errors += "- Date is not valid.\r";

    if(!isValidTime(time))
    errors += "- Time is not valid.\r";
    errors += "- Time is not valid.\r";

    if(isValidDate(date) && isValidTime(time)){
    //Build the date
    var submitDate = new Date(date);
    // Parse the date parts to integers

    // Parse the date parts to integers
    var parts = time.split(":");
    var hour = parseInt(parts[0], 10);
    var min = parseInt(parts[1], 10);
    var sec = parseInt(parts[2], 10);

    submitDate.setHours(hour, min, sec, 0);

    var now = new Date();
    var msRemaining = submitDate - now;

    var maxDays = 14;
    if(msRemaining < 0)
    errors += "- Date/Time must be in the future." + submitDate;
    errors += "- Date/Time must be in the future." + submitDate;
    else if(msRemaining > maxDays * 1000 * 60 * 60 * 24)
    errors += "- Date/Time cannot be more than " + maxDays + " days in the future." + msRemaining;
    errors += "- Date/Time cannot be more than " + maxDays + " days in the future." + msRemaining;
    }

    /*if (phoneArea.search(/\d\d\d/g) == -1 || phonePrefix.search(/\d\d\d/g) == -1 || phoneNumber.search(/\d\d\d\d/g) == -1) {
    errors += "- Invalid phone number.\r";
    }
    @@ -248,7 +258,7 @@ function beginDelay()
    GM_setValue("phonePrefix", phonePrefix);
    GM_setValue("phoneNumber", phoneNumber);
    }*/

    if(errors.length == 0){

    //Install the timeout to submit the form.
    @@ -257,10 +267,11 @@ function beginDelay()
    globalSubmitDate = submitDate;

    //Install a short term timeout to call the countdown wrapper at the beginning of the next second.
    window.setTimeout(displayCountdownWrapper, msRemaining % 1000);
    //window.setTimeout(displayCountdownWrapper, msRemaining % 1000);
    displayCountdownWrapper();
    }
    else{
    alert(errors);
    alert(errors);
    }
    }
    catch(e){
    @@ -304,8 +315,8 @@ function isValidTime(timeString)

    // Parse the date parts to integers
    var parts = timeString.split(":");
    var hour = parseInt(parts[1], 10);
    var min = parseInt(parts[0], 10);
    var hour = parseInt(parts[0], 10);
    var min = parseInt(parts[1], 10);
    var sec = parseInt(parts[2], 10);

    // Check the ranges of month and year
    @@ -333,14 +344,14 @@ function checkInPageFormEdit()

    var mainLabel = document.createElement("h2");
    mainLabel.setAttribute('class',FORM_HEADING_CLASS);

    var mainLabelDiv = document.createElement("div");
    mainLabelDiv.textContent = 'Set Check In Date and Time';

    mainLabel.appendChild(mainLabelDiv);

    dateSelect.innerHTML += "<br/>";

    dateSelect.appendChild(mainLabel);

    //The date portion.
    @@ -356,12 +367,12 @@ function checkInPageFormEdit()
    dateInput.setAttribute('type','text');
    dateInput.setAttribute('maxlength','10');
    dateInput.setAttribute('value',(today.getMonth()+1)+'/'+today.getDate()+'/'+today.getFullYear());
    // dateInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    // dateInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    dateInput.setAttribute('tabindex','7');

    dateSelect.appendChild(dateLabel);
    dateSelect.appendChild(dateInput);

    // The time portion.

    var timeLabel = document.createElement("label");
    @@ -372,17 +383,17 @@ function checkInPageFormEdit()
    timeInput.setAttribute('class','input--text');
    timeInput.setAttribute('type','text');
    timeInput.setAttribute('maxlength','8');
    timeInput.setAttribute('value',(today.getHours()+1)+':'+today.getMinutes()+':02');
    // timeInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    timeInput.setAttribute('value',(today.getHours()+1)+':'+today.getMinutes()+':05');
    // timeInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    timeInput.setAttribute('tabindex','8');

    dateSelect.appendChild(timeLabel);
    dateSelect.appendChild(timeInput);

    delayDiv.appendChild(dateSelect);

    //auto-text boarding pass section

    /*var autoTextArea = document.createElement("div");
    var textLabel = document.createElement("label");
    textLabel.innerHTML = " Boarding pass text number:";
    @@ -424,38 +435,38 @@ function checkInPageFormEdit()
    delayDiv.appendChild(autoTextArea);
    */

    // The area that displays how much time remains before the form is submitted.

    delayDiv.innerHTML += "<br/><br />";

    var countdownH2 = document.createElement("h2");
    countdownH2.setAttribute('class',FORM_HEADING_CLASS);

    var countdownDiv = document.createElement("div");
    countdownDiv.setAttribute('id','countdown');
    countdownDiv.textContent = 'Click to Start ->';

    countdownH2.appendChild(countdownDiv);
    delayDiv.appendChild(countdownH2);

    // Auto Check In button

    var delayButtonDiv = document.createElement("div");
    delayButtonDiv.setAttribute('class',BUTTON_DIV_CLASS);

    var delayButton = document.createElement("button");
    delayButton.setAttribute('class',BUTTON_CLASS);
    delayButton.setAttribute('type','button');
    delayButton.addEventListener("click", beginDelay, true);
    delayButton.setAttribute('tabindex','14');

    var delayButtonSpan = document.createElement("span");
    delayButtonSpan.textContent = 'Auto Check in';

    delayButton.appendChild(delayButtonSpan);
    delayButtonDiv.appendChild(delayButton);

    delayDiv.appendChild(delayButtonDiv);

    document.getElementsByClassName(CHECKIN_FORM_DIV_CLASS)[0].appendChild(delayDiv);
    @@ -476,16 +487,16 @@ function autoPassengerPage()
    return;

    // Check all the check boxes.
    var node_list = document.getElementsByTagName('input');
    for (var i = 0; i < node_list.length; i++) {
    var node = node_list[i];
    if (node.getAttribute('type') == 'checkbox') {
    node.checked = true;
    }
    }
    //var node_list = document.getElementsByTagName('input');
    //for (var i = 0; i < node_list.length; i++) {
    // var node = node_list[i];
    // if (node.getAttribute('type') == 'checkbox') {
    // node.checked = true;
    // }
    //}

    //Click the print button
    var button = document.getElementsByClassName()[0];
    var button = document.getElementsByClassName('air-check-in-review-results--check-in-button')[0];
    button.click();
    }
    catch(e){
    @@ -539,12 +550,12 @@ function waitForSendButton() {
    //case of the select boarding pass page (regex match the url)
    if(/review/.test(document.location.href))
    {
    autoPassengerPage();
    autoPassengerPage();
    }
    //case of the check in page
    else if(/index/.test(document.location.href))
    {
    checkInPageFormEdit();
    checkInPageFormEdit();
    }
    /*else if(/confirmation/.test(document.location.href))
    {
  4. @ryanizzo ryanizzo revised this gist Dec 17, 2017. 1 changed file with 164 additions and 170 deletions.
    334 changes: 164 additions & 170 deletions southwest_auto_checkin.user.js
    Original file line number Diff line number Diff line change
    @@ -16,48 +16,51 @@
    // @grant GM_setValue
    // ==/UserScript==

    // This program is free software: you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation, either version 3 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    // GNU General Public License for more details.
    // You should have received a copy of the GNU General Public License
    // along with this program. If not, see <http://www.gnu.org/licenses/>.
    //
    // History
    //
    // 10/2012 v1.2 Ryan Izzo (ryanizzo.com)
    // Updated to use new Southwest Check In page, added validation
    //
    // 7/2014 v1.3 Ryan Izzo (ryanizzo.com)
    // Moved script to GitHub since UserScripts appears dead
    //
    // 10/2014 v1.4 JR Hehnly (@stormchasing)
    // Added phone number entry to auto-text boarding pass docs to mobile device
    //
    // 3/28/2016 v1.5.1 Trevor McClellan (github.com/trevormcclellan)
    // Fixed phone number entry system
    //
    // 9/2017 v1.6 JR Hehnly (@stormchasing)
    // Initial changes to handle new Southwest confirmation lookup page
    //
    // 10/03/2017 v1.6.1 JR Hehnly (@stormchasing)
    // Got the script to a state where check-in works, but no auto-text boarding pass yet.
    // Have not determined what event listeners need to be triggered in the phone number form field.
    // Submits sucessfully if last phone number character is manually typed, but fails validation if it's only filled by the script.
    //
    // 12/2017 v1.7 Ryan Izzo (ryanizzo.com)
    // - Matching visual styles of page
    // - Making countdown timer larger
    // - Using constants for page values (hopefully this makes it easier to udpdate later when the pages change)
    // - Aggregating validation errors to avoid cases where you may have additional, unreported errors preventing submission
    //
    // TODO: Use Southwest's server's time instead of the client's clock.
    // TODO: Test select passenger page.
    /* This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
    History
    10/2012 v1.2 Ryan Izzo (ryanizzo.com)
    Updated to use new Southwest Check In page, added validation
    7/2014 v1.3 Ryan Izzo (ryanizzo.com)
    Moved script to GitHub since UserScripts appears dead
    10/2014 v1.4 JR Hehnly (@stormchasing)
    Added phone number entry to auto-text boarding pass docs to mobile device
    3/28/2016 v1.5.1 Trevor McClellan (github.com/trevormcclellan)
    Fixed phone number entry system
    9/2017 v1.6 JR Hehnly (@stormchasing)
    Initial changes to handle new Southwest confirmation lookup page
    10/03/2017 v1.6.1 JR Hehnly (@stormchasing)
    Got the script to a state where check-in works, but no auto-text boarding pass yet.
    Have not determined what event listeners need to be triggered in the phone number form field.
    Submits sucessfully if last phone number character is manually typed, but fails validation if it's only filled by the script.
    12/2017 v1.7 Ryan Izzo (ryanizzo.com)
    - Matching visual styles of page.
    - Making countdown timer larger.
    - Using constants for page values (hopefully this makes it easier to udpdate later when the pages change).
    - Aggregating validation errors to avoid cases where you may have additional, unreported errors preventing submission.
    - Commenting out confirmation page for texting boarding pass as this doesnt appear to be fully working.
    - Using single input for date and time
    TODO: Use Southwest's server's time instead of the client's clock.
    TODO: Test select passenger page.
    */

    ///////////// CONSTANTS ////////////////

    @@ -70,8 +73,9 @@ const CHECKIN_LASTNAME_INPUT_ID = "passengerLastName";
    const SUBMIT_BUTTON_ID = "form-mixin--submit-button";

    const FORM_HEADING_CLASS = 'heading heading_medium retrieve-reservation-form-container--form-title';
    const FORM_LABEL_CLASS = 'form-control--label';
    const FORM_TEXT_CLASS = 'form-control--label-text';
    const REQUIRED_CLASS = 'form--required-indicator';
    const INPUT_STYLE = 'border: thin #aaa solid;';
    const BUTTON_DIV_CLASS = 'form-container--search-block';
    const BUTTON_CLASS = 'actionable actionable_button actionable_large-button actionable_no-outline actionable_primary button submit-button';

    @@ -81,12 +85,12 @@ const REVIEW_SUBMIT_BUTTON_CLASS = "actionable actionable_button actionable_larg

    // Confirmation page

    const CONF_TEXT_ID = "textBoardingPass";
    //const CONF_TEXT_ID = "textBoardingPass";

    ///////////// CHECK IN PAGE ////////////////

    var globalSubmitDate;
    var allDone = false;
    //var allDone = false;

    /**
    * @brief Submit the check in form on the Southwest Check In Online page.
    @@ -154,14 +158,15 @@ function displayCountdown()
    autoPassengerPage();
    return;
    }
    else if(/confirmation/.test(document.location.href))
    /*else if(/confirmation/.test(document.location.href))
    {
    if (allDone === false)
    {
    autoTextBoardingDocs();
    }
    return;
    }
    }*/

    alert('displayCountdown: An error has occurred: ' +e.message);
    }
    }
    @@ -191,17 +196,13 @@ function beginDelay()
    var firstName = document.getElementById(CHECKIN_FIRSTNAME_INPUT_ID).value;
    var lastName = document.getElementById(CHECKIN_LASTNAME_INPUT_ID).value;

    var month = document.getElementById("month-input").value;
    var day = document.getElementById("day-input").value;
    var year = document.getElementById("year-input").value;

    var hour = document.getElementById("hour-input").value;
    var minute = document.getElementById("minute-input").value;
    var second = document.getElementById("second-input").value;
    var date = document.getElementById("date-input").value;

    var time = document.getElementById("time-input").value;

    var phoneArea = document.getElementById("phoneArea").value;
    var phonePrefix = document.getElementById("phonePrefix").value;
    var phoneNumber = document.getElementById("phoneNumber").value;
    // var phoneArea = document.getElementById("phoneArea").value;
    // var phonePrefix = document.getElementById("phonePrefix").value;
    // var phoneNumber = document.getElementById("phoneNumber").value;

    var errors = "";
    if(confNumber === "" || firstName === "" || lastName === "" )
    @@ -210,42 +211,43 @@ function beginDelay()
    if(confNumber.length != 6 )
    errors += "- Confirmation Number must be 6 characters.\r";

    if(month === "" || day === "" || year === "" || hour === "" || minute === "" || second === "" )
    errors += "- Must fill out Date and Time.\r";
    else{
    //Build a date
    var submitDate = new Date();
    //submitDate.setMonth(month - 1);
    //submitDate.setDate(day);
    submitDate.setFullYear(year, month - 1, day);
    submitDate.setHours(hour);
    submitDate.setMinutes(minute);
    submitDate.setSeconds(second);
    submitDate.setMilliseconds(0);
    if(!isValidDate(date))
    errors += "- Date is not valid.\r";

    if(!isValidTime(time))
    errors += "- Time is not valid.\r";

    if(isValidDate(date) && isValidTime(time)){
    //Build the date
    var submitDate = new Date(date);

    // Parse the date parts to integers
    var parts = time.split(":");
    var hour = parseInt(parts[0], 10);
    var min = parseInt(parts[1], 10);
    var sec = parseInt(parts[2], 10);

    submitDate.setHours(hour, min, sec, 0);

    var now = new Date();
    var msRemaining = submitDate - now;
    //alert(submitDate + " - " + now + " = " + msRemaining);

    var maxDays = 14;
    if(msRemaining < 0)
    errors += "- Date/Time must be in the future.";
    errors += "- Date/Time must be in the future." + submitDate;
    else if(msRemaining > maxDays * 1000 * 60 * 60 * 24)
    errors += "- Date/Time cannot be more than " + maxDays + " days in the future." + msRemaining;
    }

    if(year.length != 4 )
    errors += "- Year must be 4 characters.\r";

    if (phoneArea.search(/\d\d\d/g) == -1 || phonePrefix.search(/\d\d\d/g) == -1 || phoneNumber.search(/\d\d\d\d/g) == -1) {
    /*if (phoneArea.search(/\d\d\d/g) == -1 || phonePrefix.search(/\d\d\d/g) == -1 || phoneNumber.search(/\d\d\d\d/g) == -1) {
    errors += "- Invalid phone number.\r";
    }
    else{
    //save the text number for later
    GM_setValue("phoneArea", phoneArea);
    GM_setValue("phonePrefix", phonePrefix);
    GM_setValue("phoneNumber", phoneNumber);
    }
    }*/

    if(errors.length == 0){

    @@ -266,10 +268,57 @@ function beginDelay()
    }
    }

    //Validates that the input string is a valid date formatted as "mm/dd/yyyy"
    function isValidDate(dateString)
    {
    // First check for the pattern
    if(!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString))
    return false;

    // Parse the date parts to integers
    var parts = dateString.split("/");
    var day = parseInt(parts[1], 10);
    var month = parseInt(parts[0], 10);
    var year = parseInt(parts[2], 10);

    // Check the ranges of month and year
    if(year < 2017 || year > 2100 || month == 0 || month > 12)
    return false;

    var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];

    // Adjust for leap years
    if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
    monthLength[1] = 29;

    // Check the range of the day
    return day > 0 && day <= monthLength[month - 1];
    }

    //Validates that the input string is a valid date formatted as "mm/dd/yyyy"
    function isValidTime(timeString)
    {
    // First check for the pattern
    if(!/^\d{1,2}:\d{1,2}:\d{1,2}$/.test(timeString))
    return false;

    // Parse the date parts to integers
    var parts = timeString.split(":");
    var hour = parseInt(parts[1], 10);
    var min = parseInt(parts[0], 10);
    var sec = parseInt(parts[2], 10);

    // Check the ranges of month and year
    if(hour < 0 || hour > 23 || min < 0 || min > 59 || sec < 0 || sec > 59)
    return false;

    return true;
    }

    /**
    * @brief Edits the check in page; Adds Date, time, and Auto Check In button
    *
    * TODO Error handling. (Auto notify the developer when southwest page changes)
    * TODO Dater and Time picker
    */
    function checkInPageFormEdit()
    {
    @@ -299,95 +348,42 @@ function checkInPageFormEdit()
    var today = new Date();

    var dateLabel = document.createElement("label");
    dateLabel.innerHTML = " Date: (mm/dd/yyyy) <span class=\"" +REQUIRED_CLASS+"\">*</span>";

    var monthInput = document.createElement("input");
    monthInput.setAttribute('id','month-input');
    //monthInput.setAttribute('class','input--text');
    monthInput.setAttribute('type','text');
    monthInput.setAttribute('maxlength','2');
    monthInput.setAttribute('size','2');
    monthInput.setAttribute('value',today.getMonth()+1);
    // monthInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    monthInput.setAttribute('style',INPUT_STYLE);
    monthInput.setAttribute('tabindex','5');

    var dayInput = document.createElement("input");
    dayInput.setAttribute('id','day-input');
    dayInput.setAttribute('type','text');
    dayInput.setAttribute('maxlength','2');
    dayInput.setAttribute('size','2');
    dayInput.setAttribute('value',today.getDate());
    // dayInput.setAttribute('onfocus','if(this.value==\'dd\') this.value=\'\';');
    dayInput.setAttribute('style',INPUT_STYLE);
    dayInput.setAttribute('tabindex','6');

    var yearInput = document.createElement("input");
    yearInput.setAttribute('id','year-input');
    yearInput.setAttribute('type','text');
    yearInput.setAttribute('maxlength','4');
    yearInput.setAttribute('size','4');
    yearInput.setAttribute('value',today.getFullYear());
    // yearInput.setAttribute('onfocus','if(this.value==\'yyyy\') this.value=\'\';');
    yearInput.setAttribute('style',INPUT_STYLE);
    yearInput.setAttribute('tabindex','7');

    dateLabel.innerHTML = "<span class=\""+FORM_LABEL_CLASS+"\"><span class=\""+FORM_TEXT_CLASS+"\">Date: (mm/dd/yyyy)</span><span class=\"" +REQUIRED_CLASS+"\">*</span></span>";

    var dateInput = document.createElement("input");
    dateInput.setAttribute('id','date-input');
    dateInput.setAttribute('class','input--text');
    dateInput.setAttribute('type','text');
    dateInput.setAttribute('maxlength','10');
    dateInput.setAttribute('value',(today.getMonth()+1)+'/'+today.getDate()+'/'+today.getFullYear());
    // dateInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    dateInput.setAttribute('tabindex','7');

    dateSelect.appendChild(dateLabel);
    dateSelect.innerHTML += "<br/>";
    dateSelect.appendChild(monthInput);
    dateSelect.innerHTML += " / ";
    dateSelect.appendChild(dayInput);
    dateSelect.innerHTML += " / ";
    dateSelect.appendChild(yearInput);

    dateSelect.appendChild(dateInput);

    // The time portion.

    var timeLabel = document.createElement("label");
    timeLabel.innerHTML = " Time: (24-hour format) <span class=\"" +REQUIRED_CLASS+"\">*</span>";

    var hourInput = document.createElement("input");
    hourInput.setAttribute('id','hour-input');
    hourInput.setAttribute('type','text');
    hourInput.setAttribute('maxlength','2');
    hourInput.setAttribute('size','2');
    hourInput.setAttribute('value',today.getHours());
    // hourInput.setAttribute('onfocus','if(this.value==\'hh\') this.value=\'\';');
    hourInput.setAttribute('style',INPUT_STYLE);
    hourInput.setAttribute('tabindex','8');

    var minuteInput = document.createElement("input");
    minuteInput.setAttribute('id','minute-input');
    minuteInput.setAttribute('type','text');
    minuteInput.setAttribute('maxlength','2');
    minuteInput.setAttribute('size','2');
    minuteInput.setAttribute('value',today.getMinutes());
    // minuteInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    minuteInput.setAttribute('style',INPUT_STYLE);
    minuteInput.setAttribute('tabindex','9');

    var secondInput = document.createElement("input");
    secondInput.setAttribute('id','second-input');
    secondInput.setAttribute('type','text');
    secondInput.setAttribute('maxlength','2');
    secondInput.setAttribute('size','2');
    secondInput.setAttribute('value','02');
    secondInput.setAttribute('style',INPUT_STYLE);
    secondInput.setAttribute('tabindex','10');

    dateSelect.innerHTML += "<br/><br/>";

    timeLabel.innerHTML = "<span class=\""+FORM_LABEL_CLASS+"\"><span class=\""+FORM_TEXT_CLASS+"\">Time: (24-hour format hh:mm:ss)</span><span class=\"" +REQUIRED_CLASS+"\">*</span></span>";

    var timeInput = document.createElement("input");
    timeInput.setAttribute('id','time-input');
    timeInput.setAttribute('class','input--text');
    timeInput.setAttribute('type','text');
    timeInput.setAttribute('maxlength','8');
    timeInput.setAttribute('value',(today.getHours()+1)+':'+today.getMinutes()+':02');
    // timeInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    timeInput.setAttribute('tabindex','8');

    dateSelect.appendChild(timeLabel);
    dateSelect.innerHTML += "<br/>";
    dateSelect.appendChild(hourInput);
    dateSelect.innerHTML += " : ";
    dateSelect.appendChild(minuteInput);
    dateSelect.innerHTML += " : ";
    dateSelect.appendChild(secondInput);

    dateSelect.appendChild(timeInput);

    delayDiv.appendChild(dateSelect);

    //auto-text boarding pass section
    var autoTextArea = document.createElement("div");

    /*var autoTextArea = document.createElement("div");
    var textLabel = document.createElement("label");
    textLabel.innerHTML = " Boarding pass text number:";
    @@ -397,7 +393,6 @@ function checkInPageFormEdit()
    phoneArea.setAttribute('maxlength','3');
    phoneArea.setAttribute('size','3');
    phoneArea.setAttribute('value', GM_getValue("phoneArea") !== undefined ? GM_getValue("phoneArea") : '');
    phoneArea.setAttribute('style',INPUT_STYLE);
    phoneArea.setAttribute('tabindex','11');
    var phonePrefix = document.createElement("input");
    @@ -406,7 +401,6 @@ function checkInPageFormEdit()
    phonePrefix.setAttribute('maxlength','3');
    phonePrefix.setAttribute('size','3');
    phonePrefix.setAttribute('value', GM_getValue("phonePrefix") !== undefined ? GM_getValue("phonePrefix") : '');
    phonePrefix.setAttribute('style',INPUT_STYLE);
    phonePrefix.setAttribute('tabindex','12');
    var phoneNumber = document.createElement("input");
    @@ -415,7 +409,6 @@ function checkInPageFormEdit()
    phoneNumber.setAttribute('maxlength','4');
    phoneNumber.setAttribute('size','4');
    phoneNumber.setAttribute('value', GM_getValue("phoneNumber") !== undefined ? GM_getValue("phoneNumber") : '');
    phoneNumber.setAttribute('style',INPUT_STYLE);
    phoneNumber.setAttribute('tabindex','13');
    autoTextArea.innerHTML += "<br/>";
    @@ -430,11 +423,12 @@ function checkInPageFormEdit()
    autoTextArea.appendChild(phoneNumber);
    delayDiv.appendChild(autoTextArea);

    delayDiv.innerHTML += "<br/><br />";

    */

    // The area that displays how much time remains before the form is submitted.

    delayDiv.innerHTML += "<br/><br />";

    var countdownH2 = document.createElement("h2");
    countdownH2.setAttribute('class',FORM_HEADING_CLASS);

    @@ -502,7 +496,7 @@ function autoPassengerPage()

    ///////////// BOARDING DOC DELIVERY PAGE ////////////////

    function autoTextBoardingDocs()
    /*function autoTextBoardingDocs()
    {
    try{
    //find error notification
    @@ -520,15 +514,15 @@ function autoTextBoardingDocs()
    }
    /*function waitForTextBoardingPass() {
    function waitForTextBoardingPass() {
    if(document.getElementById("textBoardingPass") === null) {
    window.setTimeout(waitForTextBoardingPass, 100);
    } else {
    document.getElementById("textBoardingPass").focus();
    document.getElementById("textBoardingPass").value = parseInt(GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber"));
    waitForSendButton();
    }
    }*/
    }
    function waitForSendButton() {
    if(document.getElementById(SUBMIT_BUTTON_ID) === null || document.getElementById(CONF_TEXT_ID).value != GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber")) {
    @@ -540,7 +534,7 @@ function waitForSendButton() {
    //document.getElementById(SUBMIT_BUTTON_ID).click();
    allDone = true;
    }
    }
    }*/

    //case of the select boarding pass page (regex match the url)
    if(/review/.test(document.location.href))
    @@ -552,7 +546,7 @@ else if(/index/.test(document.location.href))
    {
    checkInPageFormEdit();
    }
    else if(/confirmation/.test(document.location.href))
    /*else if(/confirmation/.test(document.location.href))
    {
    autoTextBoardingDocs();
    }
    }*/
  5. @ryanizzo ryanizzo revised this gist Dec 17, 2017. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions southwest_auto_checkin.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace http://www.ryanizzo.com/southwest-auto-check-in/
    // @version 1.6.1
    // @namespace https://gist.github.com/ryanizzo/058829a5fafe733bd876410db7a1e699
    // @version 1.7
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
  6. @ryanizzo ryanizzo renamed this gist Dec 17, 2017. 1 changed file with 164 additions and 95 deletions.
    Original file line number Diff line number Diff line change
    @@ -9,8 +9,8 @@
    // @description Automatically check in to Southwest Airline flights at the appropriate time.
    // @include https://www.southwest.com/air/check-in/index.html*
    // @include https://www.southwest.com/flight/selectCheckinDocDelivery.html*
    // @include https://www.southwest.com/air/check-in/review.html*
    // @include https://www.southwest.com/air/check-in/confirmation.html*
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
    // @grant GM_getValue
    // @grant GM_setValue
    @@ -50,9 +50,39 @@
    // Have not determined what event listeners need to be triggered in the phone number form field.
    // Submits sucessfully if last phone number character is manually typed, but fails validation if it's only filled by the script.
    //
    // 12/2017 v1.7 Ryan Izzo (ryanizzo.com)
    // - Matching visual styles of page
    // - Making countdown timer larger
    // - Using constants for page values (hopefully this makes it easier to udpdate later when the pages change)
    // - Aggregating validation errors to avoid cases where you may have additional, unreported errors preventing submission
    //
    // TODO: Use Southwest's server's time instead of the client's clock.
    // TODO: Test select passenger page.

    ///////////// CONSTANTS ////////////////

    // Check In page

    const CHECKIN_FORM_DIV_CLASS = "air-reservation-confirmation-number-search-form";
    const CHECKIN_CONF_INPUT_ID = "confirmationNumber";
    const CHECKIN_FIRSTNAME_INPUT_ID = "passengerFirstName";
    const CHECKIN_LASTNAME_INPUT_ID = "passengerLastName";
    const SUBMIT_BUTTON_ID = "form-mixin--submit-button";

    const FORM_HEADING_CLASS = 'heading heading_medium retrieve-reservation-form-container--form-title';
    const REQUIRED_CLASS = 'form--required-indicator';
    const INPUT_STYLE = 'border: thin #aaa solid;';
    const BUTTON_DIV_CLASS = 'form-container--search-block';
    const BUTTON_CLASS = 'actionable actionable_button actionable_large-button actionable_no-outline actionable_primary button submit-button';

    // Review page

    const REVIEW_SUBMIT_BUTTON_CLASS = "actionable actionable_button actionable_large-button actionable_no-outline actionable_primary button submit-button air-check-in-review-results--check-in-button";

    // Confirmation page

    const CONF_TEXT_ID = "textBoardingPass";

    ///////////// CHECK IN PAGE ////////////////

    var globalSubmitDate;
    @@ -64,11 +94,11 @@ var allDone = false;
    function submitNow()
    {
    try{
    var submitButton = document.getElementById("form-mixin--submit-button");
    var submitButton = document.getElementById(SUBMIT_BUTTON_ID);
    submitButton.click();
    }
    catch(e){
    alert('globalSubmitDate: An error has occurred: '+ e.message);
    alert('submitNow: An error has occurred: '+ e.message);
    }
    }

    @@ -81,35 +111,41 @@ function submitNow()
    function displayCountdown()
    {
    try{
    var area = document.getElementById("countdown");
    var countdown = document.getElementById("countdown");

    var timeRemain = globalSubmitDate - new Date();
    var days = Math.floor(timeRemain / (1000 * 60 * 60 * 24));
    var hours = Math.floor(timeRemain / (1000 * 60 * 60)) % 24;
    var minutes = Math.floor(timeRemain / (1000 * 60)) % 60;
    //round to the nearest second
    var seconds = Math.round(timeRemain / 1000) % 60;

    //Don't print negative time.
    if (hours < 0 || minutes < 0 || seconds < 0)
    {
    area.innerHTML = "Checking In...";
    countdown.nodeValue = "Checking In...";
    return;
    }
    area.innerHTML = "Time Remaining: <strong>";

    var time = '';
    //If 0 days remain, omit them.
    if (days !== 0)
    area.innerHTML += days + "d ";
    time += days + "d ";
    //If 0 hours remain, omit them.
    if (hours !== 0)
    area.innerHTML += hours + "h ";
    time += hours + "h ";
    //Add padding to minute
    if (minutes !==0 )
    //area.innerHTML += "0";
    area.innerHTML += minutes + "m ";
    time += minutes + "m ";
    //Add padding to second
    //if (seconds < 10)
    //area.innerHTML += "0";
    area.innerHTML += seconds;
    area.innerHTML += "s</strong>";
    time += seconds;
    time += "s";

    countdown.textContent = time;

    }
    catch(e){
    // has the page changed?
    @@ -151,9 +187,9 @@ function displayCountdownWrapper()
    function beginDelay()
    {
    try{
    var confNumber = document.getElementById("confirmationNumber").value;
    var firstName = document.getElementById("passengerFirstName").value;
    var lastName = document.getElementById("passengerLastName").value;
    var confNumber = document.getElementById(CHECKIN_CONF_INPUT_ID).value;
    var firstName = document.getElementById(CHECKIN_FIRSTNAME_INPUT_ID).value;
    var lastName = document.getElementById(CHECKIN_LASTNAME_INPUT_ID).value;

    var month = document.getElementById("month-input").value;
    var day = document.getElementById("day-input").value;
    @@ -167,25 +203,16 @@ function beginDelay()
    var phonePrefix = document.getElementById("phonePrefix").value;
    var phoneNumber = document.getElementById("phoneNumber").value;

    if(confNumber === "" || firstName === "" || lastName === "" ){
    alert("Must fill out Confirmation Number and Name.");
    }
    else if(month === "" || month === "mm" || day === "" || day == "dd" || year === "" || year == "yyyy" ||
    hour === "" || hour == "hh" || minute === "" || minute == "mm" || second === "" ){
    alert("Must fill out Date and Time.");
    }
    else if(year.length < 4 ){
    alert("Year must be 4 characters.");
    }
    else if (phoneArea.search(/\d\d\d/g) == -1 || phonePrefix.search(/\d\d\d/g) == -1 || phoneNumber.search(/\d\d\d\d/g) == -1) {
    alert("Invalid phone number provided.");
    }
    var errors = "";
    if(confNumber === "" || firstName === "" || lastName === "" )
    errors += "- Must fill out Confirmation Number, First Name and Last Name.\r";

    if(confNumber.length != 6 )
    errors += "- Confirmation Number must be 6 characters.\r";

    if(month === "" || day === "" || year === "" || hour === "" || minute === "" || second === "" )
    errors += "- Must fill out Date and Time.\r";
    else{
    //save the text number for later
    GM_setValue("phoneArea", phoneArea);
    GM_setValue("phonePrefix", phonePrefix);
    GM_setValue("phoneNumber", phoneNumber);

    //Build a date
    var submitDate = new Date();
    //submitDate.setMonth(month - 1);
    @@ -202,18 +229,36 @@ function beginDelay()

    var maxDays = 14;
    if(msRemaining < 0)
    alert("Date/Time must be in the future.");
    errors += "- Date/Time must be in the future.";
    else if(msRemaining > maxDays * 1000 * 60 * 60 * 24)
    alert("Date/Time cannot be more than " + maxDays + " days in the future." + msRemaining);
    else{
    //Install the timeout to submit the form.
    window.setTimeout(submitNow, msRemaining);
    errors += "- Date/Time cannot be more than " + maxDays + " days in the future." + msRemaining;
    }

    globalSubmitDate = submitDate;
    if(year.length != 4 )
    errors += "- Year must be 4 characters.\r";

    if (phoneArea.search(/\d\d\d/g) == -1 || phonePrefix.search(/\d\d\d/g) == -1 || phoneNumber.search(/\d\d\d\d/g) == -1) {
    errors += "- Invalid phone number.\r";
    }
    else{
    //save the text number for later
    GM_setValue("phoneArea", phoneArea);
    GM_setValue("phonePrefix", phonePrefix);
    GM_setValue("phoneNumber", phoneNumber);
    }

    if(errors.length == 0){

    //Install a short term timeout to call the countdown wrapper at the beginning of the next second.
    window.setTimeout(displayCountdownWrapper, msRemaining % 1000);
    }
    //Install the timeout to submit the form.
    window.setTimeout(submitNow, msRemaining);

    globalSubmitDate = submitDate;

    //Install a short term timeout to call the countdown wrapper at the beginning of the next second.
    window.setTimeout(displayCountdownWrapper, msRemaining % 1000);
    }
    else{
    alert(errors);
    }
    }
    catch(e){
    @@ -229,9 +274,6 @@ function beginDelay()
    function checkInPageFormEdit()
    {
    try{
    var leftPanel = document.getElementsByClassName("air-reservation-confirmation-number-search-form")[0];

    //All of our stuff will go in this div.

    var delayDiv = document.createElement("div");
    delayDiv.setAttribute('id','checkInDelay');
    @@ -240,28 +282,34 @@ function checkInPageFormEdit()

    //The big label at the top of the menu

    var mainLabel = document.createElement("h4");
    mainLabel.setAttribute('class','swa_feature_checkInOnline_form_header');
    mainLabel.innerHTML = "Set Check In Date and Time";
    var mainLabel = document.createElement("h2");
    mainLabel.setAttribute('class',FORM_HEADING_CLASS);

    var mainLabelDiv = document.createElement("div");
    mainLabelDiv.textContent = 'Set Check In Date and Time';

    mainLabel.appendChild(mainLabelDiv);

    dateSelect.innerHTML += "<br/>";

    dateSelect.appendChild(mainLabel);

    //The date portion.

    var today = new Date();


    var dateLabel = document.createElement("label");
    dateLabel.innerHTML = "<span class=\"required\">*</span> Date:";
    dateLabel.innerHTML = " Date: (mm/dd/yyyy) <span class=\"" +REQUIRED_CLASS+"\">*</span>";

    var monthInput = document.createElement("input");
    monthInput.setAttribute('id','month-input');
    //monthInput.setAttribute('class','input--text');
    monthInput.setAttribute('type','text');
    monthInput.setAttribute('maxlength','2');
    monthInput.setAttribute('size','2');
    monthInput.setAttribute('value',today.getMonth()+1);
    monthInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    monthInput.setAttribute('style','margin-left:7em');
    // monthInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    monthInput.setAttribute('style',INPUT_STYLE);
    monthInput.setAttribute('tabindex','5');

    var dayInput = document.createElement("input");
    @@ -270,7 +318,8 @@ function checkInPageFormEdit()
    dayInput.setAttribute('maxlength','2');
    dayInput.setAttribute('size','2');
    dayInput.setAttribute('value',today.getDate());
    dayInput.setAttribute('onfocus','if(this.value==\'dd\') this.value=\'\';');
    // dayInput.setAttribute('onfocus','if(this.value==\'dd\') this.value=\'\';');
    dayInput.setAttribute('style',INPUT_STYLE);
    dayInput.setAttribute('tabindex','6');

    var yearInput = document.createElement("input");
    @@ -279,29 +328,31 @@ function checkInPageFormEdit()
    yearInput.setAttribute('maxlength','4');
    yearInput.setAttribute('size','4');
    yearInput.setAttribute('value',today.getFullYear());
    yearInput.setAttribute('onfocus','if(this.value==\'yyyy\') this.value=\'\';');
    // yearInput.setAttribute('onfocus','if(this.value==\'yyyy\') this.value=\'\';');
    yearInput.setAttribute('style',INPUT_STYLE);
    yearInput.setAttribute('tabindex','7');

    dateSelect.appendChild(dateLabel);
    dateSelect.innerHTML += "<br/>";
    dateSelect.appendChild(monthInput);
    dateSelect.innerHTML += "/";
    dateSelect.innerHTML += " / ";
    dateSelect.appendChild(dayInput);
    dateSelect.innerHTML += "/";
    dateSelect.innerHTML += " / ";
    dateSelect.appendChild(yearInput);

    // The time portion.

    var timeLabel = document.createElement("label");
    timeLabel.innerHTML = "<span class=\"required\">*</span> Time: (24-hour format) ";
    timeLabel.innerHTML = " Time: (24-hour format) <span class=\"" +REQUIRED_CLASS+"\">*</span>";

    var hourInput = document.createElement("input");
    hourInput.setAttribute('id','hour-input');
    hourInput.setAttribute('type','text');
    hourInput.setAttribute('maxlength','2');
    //hourInput.setAttribute('style','margin-left:10px');
    hourInput.setAttribute('size','2');
    hourInput.setAttribute('value',today.getHours());
    hourInput.setAttribute('onfocus','if(this.value==\'hh\') this.value=\'\';');
    // hourInput.setAttribute('onfocus','if(this.value==\'hh\') this.value=\'\';');
    hourInput.setAttribute('style',INPUT_STYLE);
    hourInput.setAttribute('tabindex','8');

    var minuteInput = document.createElement("input");
    @@ -310,7 +361,8 @@ function checkInPageFormEdit()
    minuteInput.setAttribute('maxlength','2');
    minuteInput.setAttribute('size','2');
    minuteInput.setAttribute('value',today.getMinutes());
    minuteInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    // minuteInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    minuteInput.setAttribute('style',INPUT_STYLE);
    minuteInput.setAttribute('tabindex','9');

    var secondInput = document.createElement("input");
    @@ -319,83 +371,100 @@ function checkInPageFormEdit()
    secondInput.setAttribute('maxlength','2');
    secondInput.setAttribute('size','2');
    secondInput.setAttribute('value','02');
    secondInput.setAttribute('style',INPUT_STYLE);
    secondInput.setAttribute('tabindex','10');

    dateSelect.innerHTML += "<br/><br/>";

    dateSelect.appendChild(timeLabel);
    dateSelect.innerHTML += "<br/>";
    dateSelect.appendChild(hourInput);
    dateSelect.innerHTML += ":";
    dateSelect.innerHTML += " : ";
    dateSelect.appendChild(minuteInput);
    dateSelect.innerHTML += ":";
    dateSelect.innerHTML += " : ";
    dateSelect.appendChild(secondInput);

    delayDiv.appendChild(dateSelect);

    //auto-text boarding pass section
    var autoTextArea = document.createElement("div");
    var textLabel = document.createElement("label");
    textLabel.innerHTML = "<span class=\"required\">*</span> Boarding pass text number: ";
    textLabel.innerHTML = " Boarding pass text number:";

    var phoneArea = document.createElement("input");
    phoneArea.setAttribute('id','phoneArea');
    phoneArea.setAttribute('type','text');
    phoneArea.setAttribute('maxlength','3');
    phoneArea.setAttribute('size','3');
    phoneArea.setAttribute('value', GM_getValue("phoneArea") !== undefined ? GM_getValue("phoneArea") : '');
    phoneArea.setAttribute('tabindex','12');
    phoneArea.setAttribute('style',INPUT_STYLE);
    phoneArea.setAttribute('tabindex','11');

    var phonePrefix = document.createElement("input");
    phonePrefix.setAttribute('id','phonePrefix');
    phonePrefix.setAttribute('type','text');
    phonePrefix.setAttribute('maxlength','3');
    phonePrefix.setAttribute('size','3');
    phonePrefix.setAttribute('value', GM_getValue("phonePrefix") !== undefined ? GM_getValue("phonePrefix") : '');
    phonePrefix.setAttribute('tabindex','13');
    phonePrefix.setAttribute('style',INPUT_STYLE);
    phonePrefix.setAttribute('tabindex','12');

    var phoneNumber = document.createElement("input");
    phoneNumber.setAttribute('id','phoneNumber');
    phoneNumber.setAttribute('type','text');
    phoneNumber.setAttribute('maxlength','4');
    phoneNumber.setAttribute('size','4');
    phoneNumber.setAttribute('value', GM_getValue("phoneNumber") !== undefined ? GM_getValue("phoneNumber") : '');
    phoneNumber.setAttribute('tabindex','14');
    phoneNumber.setAttribute('style',INPUT_STYLE);
    phoneNumber.setAttribute('tabindex','13');

    autoTextArea.innerHTML += "<br/>";

    autoTextArea.appendChild(textLabel);
    autoTextArea.innerHTML += "<br/>";
    autoTextArea.innerHTML += "(";
    autoTextArea.appendChild(phoneArea);
    autoTextArea.innerHTML += ")";
    autoTextArea.innerHTML += ") ";
    autoTextArea.appendChild(phonePrefix);
    autoTextArea.innerHTML += "-";
    autoTextArea.innerHTML += " - ";
    autoTextArea.appendChild(phoneNumber);

    delayDiv.appendChild(autoTextArea);

    delayDiv.innerHTML += "<br/><br />";

    // The area that displays how much time remains before the form is submitted.

    var countdownArea = document.createElement("div");
    countdownArea.setAttribute('id','countdown');
    countdownArea.innerHTML = "Click to start countdown";

    delayDiv.appendChild(countdownArea);

    var countdownH2 = document.createElement("h2");
    countdownH2.setAttribute('class',FORM_HEADING_CLASS);

    var countdownDiv = document.createElement("div");
    countdownDiv.setAttribute('id','countdown');
    countdownDiv.textContent = 'Click to Start ->';

    countdownH2.appendChild(countdownDiv);
    delayDiv.appendChild(countdownH2);

    // Auto Check In button

    var delayButton = document.createElement("input");
    delayButton.setAttribute('id','delay-button');
    var delayButtonDiv = document.createElement("div");
    delayButtonDiv.setAttribute('class',BUTTON_DIV_CLASS);

    var delayButton = document.createElement("button");
    delayButton.setAttribute('class',BUTTON_CLASS);
    delayButton.setAttribute('type','button');
    delayButton.setAttribute('style','float: right; background-color: #FFBF27; color: #111B40: font: bold 17px/1 Arial');
    delayButton.setAttribute('value','Auto Check In');
    delayButton.addEventListener("click", beginDelay, true);
    delayButton.setAttribute('tabindex','11');

    delayDiv.appendChild(delayButton);

    leftPanel.appendChild(delayDiv);
    delayButton.setAttribute('tabindex','14');

    var delayButtonSpan = document.createElement("span");
    delayButtonSpan.textContent = 'Auto Check in';

    delayButton.appendChild(delayButtonSpan);
    delayButtonDiv.appendChild(delayButton);

    delayDiv.appendChild(delayButtonDiv);

    document.getElementsByClassName(CHECKIN_FORM_DIV_CLASS)[0].appendChild(delayDiv);
    }
    catch(e){
    alert('checkInPageFormEdit: An error has occurred: ' +e.message);
    @@ -422,7 +491,7 @@ function autoPassengerPage()
    }

    //Click the print button
    var button = document.getElementsByClassName("actionable actionable_button actionable_large-button actionable_no-outline actionable_primary button submit-button air-check-in-review-results--check-in-button")[0];
    var button = document.getElementsByClassName()[0];
    button.click();
    }
    catch(e){
    @@ -441,7 +510,7 @@ function autoTextBoardingDocs()
    return;

    //click the Text button
    var button = document.getElementsByClassName("actionable actionable_button actionable_full-width actionable_large-button actionable_no-outline actionable_prefix actionable_secondary-dark-affix button boarding-pass-options--button-text")[0];
    var button = document.getElementsByClassName(REVIEW_SUBMIT_BUTTON_CLASS)[0];
    button.click();
    window.setTimeout(waitForSendButton, 500);
    }
    @@ -451,39 +520,39 @@ function autoTextBoardingDocs()

    }

    function waitForTextBoardingPass() {
    /*function waitForTextBoardingPass() {
    if(document.getElementById("textBoardingPass") === null) {
    window.setTimeout(waitForTextBoardingPass, 100);
    } else {
    document.getElementById("textBoardingPass").focus();
    document.getElementById("textBoardingPass").value = parseInt(GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber"));
    waitForSendButton();
    }
    }
    }*/

    function waitForSendButton() {
    if(document.getElementById("form-mixin--submit-button") === null || document.getElementById("textBoardingPass").value != GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber")) {
    document.getElementById("textBoardingPass").focus();
    document.getElementById("textBoardingPass").value = parseInt(GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber"));
    if(document.getElementById(SUBMIT_BUTTON_ID) === null || document.getElementById(CONF_TEXT_ID).value != GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber")) {
    document.getElementById(CONF_TEXT_ID).focus();
    document.getElementById(CONF_TEXT_ID).value = parseInt(GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber"));
    window.setTimeout(waitForSendButton, 100);
    } else {
    //document.getElementById("form-mixin--submit-button").focus();
    //document.getElementById("form-mixin--submit-button").click();
    //document.getElementById(SUBMIT_BUTTON_ID).focus();
    //document.getElementById(SUBMIT_BUTTON_ID).click();
    allDone = true;
    }
    }

    //case of the select boarding pass page (regex match the url)
    if(/review/.test(document.location.href))
    {
    autoPassengerPage();
    autoPassengerPage();
    }
    //case of the check in page
    else if(/index/.test(document.location.href))
    {
    checkInPageFormEdit();
    checkInPageFormEdit();
    }
    else if(/confirmation/.test(document.location.href))
    {
    autoTextBoardingDocs();
    }
    autoTextBoardingDocs();
    }
  7. @stormchasing stormchasing revised this gist Oct 3, 2017. 1 changed file with 60 additions and 29 deletions.
    89 changes: 60 additions & 29 deletions Auto Check-In to Southwest Flights.user.js
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,15 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace http://www.ryanizzo.com/southwest-auto-check-in/
    // @version 1.6
    // @version 1.6.1
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    // @contributor Trevor McClellan (github.com/trevormcclellan)
    // @description Automatically check in to Southwest Airline flights at the appropriate time.
    // @include https://www.southwest.com/air/check-in/index.html*
    // @include https://www.southwest.com/flight/selectCheckinDocDelivery.html*
    // @include https://www.southwest.com/flight/selectPrintDocument*
    // @include https://www.southwest.com/air/check-in/confirmation.html*
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
    // @grant GM_getValue
    @@ -36,34 +36,39 @@
    // 7/2014 v1.3 Ryan Izzo (ryanizzo.com)
    // Moved script to GitHub since UserScripts appears dead
    //
    // 10/2014 v1.4 JR Hehnly (okstorms.com)
    // 10/2014 v1.4 JR Hehnly (@stormchasing)
    // Added phone number entry to auto-text boarding pass docs to mobile device
    //
    // 3/28/2016 v1.5.1 Trevor McClellan (github.com/trevormcclellan)
    // Fixed phone number entry system
    //
    // 9/2017 v1.6 JR Hehnly (okstorms.com)
    // 9/2017 v1.6 JR Hehnly (@stormchasing)
    // Initial changes to handle new Southwest confirmation lookup page
    //
    // 10/03/2017 v1.6.1 JR Hehnly (@stormchasing)
    // Got the script to a state where check-in works, but no auto-text boarding pass yet.
    // Have not determined what event listeners need to be triggered in the phone number form field.
    // Submits sucessfully if last phone number character is manually typed, but fails validation if it's only filled by the script.
    //
    // TODO: Use Southwest's server's time instead of the client's clock.
    // TODO: Test select passenger page.

    ///////////// CHECK IN PAGE ////////////////

    var globalSubmitDate;
    var allDone = false;

    /**
    * @brief Submit the check in form on the Southwest Check In Online page.
    */
    function submitNow()
    {
    try{
    //alert(msRemaining + " " + globalSubmitDate);
    var submitButton = document.getElementById("form-mixin--submit-button");
    submitButton.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    alert('globalSubmitDate: An error has occurred: '+ e.message);
    }
    }

    @@ -107,7 +112,21 @@ function displayCountdown()
    area.innerHTML += "s</strong>";
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    // has the page changed?
    if(/review/.test(document.location.href))
    {
    autoPassengerPage();
    return;
    }
    else if(/confirmation/.test(document.location.href))
    {
    if (allDone === false)
    {
    autoTextBoardingDocs();
    }
    return;
    }
    alert('displayCountdown: An error has occurred: ' +e.message);
    }
    }

    @@ -121,7 +140,7 @@ function displayCountdownWrapper()
    window.setInterval(displayCountdown, 1000);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    alert('displayCountdownWrapper:" An error has occurred: ' +e.message);
    }
    }

    @@ -198,7 +217,7 @@ function beginDelay()
    }
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    alert('beginDelay: An error has occurred: '+ e.message);
    }
    }

    @@ -379,7 +398,7 @@ function checkInPageFormEdit()
    leftPanel.appendChild(delayDiv);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    alert('checkInPageFormEdit: An error has occurred: ' +e.message);
    }
    }

    @@ -403,11 +422,11 @@ function autoPassengerPage()
    }

    //Click the print button
    var button = document.getElementById("printDocumentsButton");
    var button = document.getElementsByClassName("actionable actionable_button actionable_large-button actionable_no-outline actionable_primary button submit-button air-check-in-review-results--check-in-button")[0];
    button.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    alert('autoPassengerPage: An error has occurred: '+ e.message);
    }

    }
    @@ -421,38 +440,50 @@ function autoTextBoardingDocs()
    if (document.title == "Error")
    return;

    //check the Text checkbox if it's there
    var textCheckbox = document.getElementById("optionText");
    if (textCheckbox === null || !GM_getValue("phoneArea") || !GM_getValue("phonePrefix") || !GM_getValue("phoneNumber"))
    return;
    textCheckbox.checked = "checked";

    //fill the mobile number
    var phoneArea = document.getElementById("phoneArea").value = GM_getValue( "phoneArea");
    var phonePrefix = document.getElementById("phonePrefix").value = GM_getValue("phonePrefix");
    var phoneNumber = document.getElementById("phoneNumber").value = GM_getValue("phoneNumber");

    //Click the continue button
    var button = document.getElementById("checkin_button");
    //click the Text button
    var button = document.getElementsByClassName("actionable actionable_button actionable_full-width actionable_large-button actionable_no-outline actionable_prefix actionable_secondary-dark-affix button boarding-pass-options--button-text")[0];
    button.click();
    window.setTimeout(waitForSendButton, 500);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    alert('autoTextBoardingDocs: An error has occurred: '+ e.message);
    }

    }

    function waitForTextBoardingPass() {
    if(document.getElementById("textBoardingPass") === null) {
    window.setTimeout(waitForTextBoardingPass, 100);
    } else {
    document.getElementById("textBoardingPass").focus();
    document.getElementById("textBoardingPass").value = parseInt(GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber"));
    waitForSendButton();
    }
    }

    function waitForSendButton() {
    if(document.getElementById("form-mixin--submit-button") === null || document.getElementById("textBoardingPass").value != GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber")) {
    document.getElementById("textBoardingPass").focus();
    document.getElementById("textBoardingPass").value = parseInt(GM_getValue("phoneArea") + GM_getValue("phonePrefix") + GM_getValue("phoneNumber"));
    window.setTimeout(waitForSendButton, 100);
    } else {
    //document.getElementById("form-mixin--submit-button").focus();
    //document.getElementById("form-mixin--submit-button").click();
    allDone = true;
    }
    }

    //case of the select boarding pass page (regex match the url)
    if(/selectPrintDocument/.test(document.location.href))
    if(/review/.test(document.location.href))
    {
    autoPassengerPage();
    }
    //case of the check in page
    else if(/check-in/.test(document.location.href))
    else if(/index/.test(document.location.href))
    {
    checkInPageFormEdit();
    }
    else if(/selectCheckinDocDelivery/.test(document.location.href))
    else if(/confirmation/.test(document.location.href))
    {
    autoTextBoardingDocs();
    }
  8. @stormchasing stormchasing revised this gist Sep 14, 2017. 1 changed file with 12 additions and 11 deletions.
    23 changes: 12 additions & 11 deletions Auto Check-In to Southwest Flights.user.js
    Original file line number Diff line number Diff line change
    @@ -1,15 +1,13 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace http://www.ryanizzo.com/southwest-auto-check-in/
    // @version 1.5.1
    // @version 1.6
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    // @contributor Trevor McClellan (github.com/trevormcclellan)
    // @description Automatically check in to Southwest Airline flights at the appropriate time.
    // @include https://southwest.com/flight/retrieveCheckinDoc.html*
    // @include https://southwest.com/flight/selectPrintDocument*
    // @include https://www.southwest.com/flight/retrieveCheckinDoc.html*
    // @include https://www.southwest.com/air/check-in/index.html*
    // @include https://www.southwest.com/flight/selectCheckinDocDelivery.html*
    // @include https://www.southwest.com/flight/selectPrintDocument*
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    @@ -44,6 +42,9 @@
    // 3/28/2016 v1.5.1 Trevor McClellan (github.com/trevormcclellan)
    // Fixed phone number entry system
    //
    // 9/2017 v1.6 JR Hehnly (okstorms.com)
    // Initial changes to handle new Southwest confirmation lookup page
    //
    // TODO: Use Southwest's server's time instead of the client's clock.
    // TODO: Test select passenger page.

    @@ -58,8 +59,8 @@ function submitNow()
    {
    try{
    //alert(msRemaining + " " + globalSubmitDate);
    var form = document.getElementById("itineraryLookup");
    form.submit();
    var submitButton = document.getElementById("form-mixin--submit-button");
    submitButton.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    @@ -132,8 +133,8 @@ function beginDelay()
    {
    try{
    var confNumber = document.getElementById("confirmationNumber").value;
    var firstName = document.getElementById("firstName").value;
    var lastName = document.getElementById("lastName").value;
    var firstName = document.getElementById("passengerFirstName").value;
    var lastName = document.getElementById("passengerLastName").value;

    var month = document.getElementById("month-input").value;
    var day = document.getElementById("day-input").value;
    @@ -209,7 +210,7 @@ function beginDelay()
    function checkInPageFormEdit()
    {
    try{
    var leftPanel = document.getElementsByClassName("checkIn_form_leftPanel")[0];
    var leftPanel = document.getElementsByClassName("air-reservation-confirmation-number-search-form")[0];

    //All of our stuff will go in this div.

    @@ -368,7 +369,7 @@ function checkInPageFormEdit()
    var delayButton = document.createElement("input");
    delayButton.setAttribute('id','delay-button');
    delayButton.setAttribute('type','button');
    delayButton.setAttribute('style','float: right; background-color: #FF3300; color: white');
    delayButton.setAttribute('style','float: right; background-color: #FFBF27; color: #111B40: font: bold 17px/1 Arial');
    delayButton.setAttribute('value','Auto Check In');
    delayButton.addEventListener("click", beginDelay, true);
    delayButton.setAttribute('tabindex','11');
    @@ -447,7 +448,7 @@ if(/selectPrintDocument/.test(document.location.href))
    autoPassengerPage();
    }
    //case of the check in page
    else if(/retrieveCheckinDoc/.test(document.location.href))
    else if(/check-in/.test(document.location.href))
    {
    checkInPageFormEdit();
    }
  9. @stormchasing stormchasing revised this gist Apr 27, 2016. 1 changed file with 6 additions and 5 deletions.
    11 changes: 6 additions & 5 deletions Auto Check-In to Southwest Flights.user.js
    Original file line number Diff line number Diff line change
    @@ -1,10 +1,11 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace http://www.ryanizzo.com/southwest-auto-check-in/
    // @version 1.6
    // @version 1.5.1
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    // @contributor Trevor McClellan (github.com/trevormcclellan)
    // @description Automatically check in to Southwest Airline flights at the appropriate time.
    // @include https://southwest.com/flight/retrieveCheckinDoc.html*
    // @include https://southwest.com/flight/selectPrintDocument*
    @@ -40,8 +41,8 @@
    // 10/2014 v1.4 JR Hehnly (okstorms.com)
    // Added phone number entry to auto-text boarding pass docs to mobile device
    //
    // 4/2016 v1.6 JR Hehnly (okstorms.com)
    // Had to update for access to GM_getValue
    // 3/28/2016 v1.5.1 Trevor McClellan (github.com/trevormcclellan)
    // Fixed phone number entry system
    //
    // TODO: Use Southwest's server's time instead of the client's clock.
    // TODO: Test select passenger page.
    @@ -420,7 +421,7 @@ function autoTextBoardingDocs()
    return;

    //check the Text checkbox if it's there
    var textCheckbox = document.getElementById("optionText1");
    var textCheckbox = document.getElementById("optionText");
    if (textCheckbox === null || !GM_getValue("phoneArea") || !GM_getValue("phonePrefix") || !GM_getValue("phoneNumber"))
    return;
    textCheckbox.checked = "checked";
    @@ -453,4 +454,4 @@ else if(/retrieveCheckinDoc/.test(document.location.href))
    else if(/selectCheckinDocDelivery/.test(document.location.href))
    {
    autoTextBoardingDocs();
    }
    }
  10. @stormchasing stormchasing revised this gist Apr 27, 2016. 1 changed file with 0 additions and 8 deletions.
    8 changes: 0 additions & 8 deletions Auto Check-In to Southwest Flights.user.js
    Original file line number Diff line number Diff line change
    @@ -13,18 +13,10 @@
    // @include https://www.southwest.com/flight/selectPrintDocument*
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
    // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
    // @grant GM_getValue
    // @grant GM_setValue
    // ==/UserScript==

    $("#wmd-input").on ("contextmenu", function (e) {
    e.preventDefault ();

    //-- Important: note the comma and the correct case for `true`.
    console.log ("GM_getValue: ", GM_getValue ("extra_markdown", true) );
    });

    // This program is free software: you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation, either version 3 of the License, or
  11. @stormchasing stormchasing revised this gist Apr 27, 2016. 1 changed file with 26 additions and 14 deletions.
    40 changes: 26 additions & 14 deletions Auto Check-In to Southwest Flights.user.js
    Original file line number Diff line number Diff line change
    @@ -1,7 +1,7 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace http://www.ryanizzo.com/southwest-auto-check-in/
    // @version 1.5
    // @version 1.6
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    @@ -13,8 +13,18 @@
    // @include https://www.southwest.com/flight/selectPrintDocument*
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html

    // @require http://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js
    // @grant GM_getValue
    // @grant GM_setValue
    // ==/UserScript==

    $("#wmd-input").on ("contextmenu", function (e) {
    e.preventDefault ();

    //-- Important: note the comma and the correct case for `true`.
    console.log ("GM_getValue: ", GM_getValue ("extra_markdown", true) );
    });

    // This program is free software: you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation, either version 3 of the License, or
    @@ -38,6 +48,9 @@
    // 10/2014 v1.4 JR Hehnly (okstorms.com)
    // Added phone number entry to auto-text boarding pass docs to mobile device
    //
    // 4/2016 v1.6 JR Hehnly (okstorms.com)
    // Had to update for access to GM_getValue
    //
    // TODO: Use Southwest's server's time instead of the client's clock.
    // TODO: Test select passenger page.

    @@ -84,13 +97,13 @@ function displayCountdown()
    }
    area.innerHTML = "Time Remaining: <strong>";
    //If 0 days remain, omit them.
    if (days != 0)
    if (days !== 0)
    area.innerHTML += days + "d ";
    //If 0 hours remain, omit them.
    if (hours != 0)
    if (hours !== 0)
    area.innerHTML += hours + "h ";
    //Add padding to minute
    if (minutes !=0 )
    if (minutes !==0 )
    //area.innerHTML += "0";
    area.innerHTML += minutes + "m ";
    //Add padding to second
    @@ -141,11 +154,11 @@ function beginDelay()
    var phonePrefix = document.getElementById("phonePrefix").value;
    var phoneNumber = document.getElementById("phoneNumber").value;

    if(confNumber == "" || firstName == "" || lastName == "" ){
    if(confNumber === "" || firstName === "" || lastName === "" ){
    alert("Must fill out Confirmation Number and Name.");
    }
    else if(month == "" || month == "mm" || day == "" || day == "dd" || year == "" || year == "yyyy"
    || hour == "" || hour == "hh" || minute == "" || minute == "mm" || second == "" ){
    else if(month === "" || month === "mm" || day === "" || day == "dd" || year === "" || year == "yyyy" ||
    hour === "" || hour == "hh" || minute === "" || minute == "mm" || second === "" ){
    alert("Must fill out Date and Time.");
    }
    else if(year.length < 4 ){
    @@ -316,23 +329,23 @@ function checkInPageFormEdit()
    phoneArea.setAttribute('type','text');
    phoneArea.setAttribute('maxlength','3');
    phoneArea.setAttribute('size','3');
    phoneArea.setAttribute('value', GM_getValue("phoneArea") != undefined ? GM_getValue("phoneArea") : '');
    phoneArea.setAttribute('value', GM_getValue("phoneArea") !== undefined ? GM_getValue("phoneArea") : '');
    phoneArea.setAttribute('tabindex','12');

    var phonePrefix = document.createElement("input");
    phonePrefix.setAttribute('id','phonePrefix');
    phonePrefix.setAttribute('type','text');
    phonePrefix.setAttribute('maxlength','3');
    phonePrefix.setAttribute('size','3');
    phonePrefix.setAttribute('value', GM_getValue("phonePrefix") != undefined ? GM_getValue("phonePrefix") : '');
    phonePrefix.setAttribute('value', GM_getValue("phonePrefix") !== undefined ? GM_getValue("phonePrefix") : '');
    phonePrefix.setAttribute('tabindex','13');

    var phoneNumber = document.createElement("input");
    phoneNumber.setAttribute('id','phoneNumber');
    phoneNumber.setAttribute('type','text');
    phoneNumber.setAttribute('maxlength','4');
    phoneNumber.setAttribute('size','4');
    phoneNumber.setAttribute('value', GM_getValue("phoneNumber") != undefined ? GM_getValue("phoneNumber") : '');
    phoneNumber.setAttribute('value', GM_getValue("phoneNumber") !== undefined ? GM_getValue("phoneNumber") : '');
    phoneNumber.setAttribute('tabindex','14');

    autoTextArea.innerHTML += "<br/>";
    @@ -416,7 +429,7 @@ function autoTextBoardingDocs()

    //check the Text checkbox if it's there
    var textCheckbox = document.getElementById("optionText1");
    if (textCheckbox == null || !GM_getValue("phoneArea") || !GM_getValue("phonePrefix") || !GM_getValue("phoneNumber"))
    if (textCheckbox === null || !GM_getValue("phoneArea") || !GM_getValue("phonePrefix") || !GM_getValue("phoneNumber"))
    return;
    textCheckbox.checked = "checked";

    @@ -448,5 +461,4 @@ else if(/retrieveCheckinDoc/.test(document.location.href))
    else if(/selectCheckinDocDelivery/.test(document.location.href))
    {
    autoTextBoardingDocs();
    }

    }
  12. @stormchasing stormchasing revised this gist Jan 4, 2015. 1 changed file with 6 additions and 6 deletions.
    12 changes: 6 additions & 6 deletions Auto Check-In to Southwest Flights.user.js
    Original file line number Diff line number Diff line change
    @@ -1,16 +1,16 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace http://www.ryanizzo.com/southwest-auto-check-in/
    // @version 1.4
    // @version 1.5
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    // @description Automatically check in to Southwest Airline flights at the appropriate time.
    // @include http://southwest.com/flight/retrieveCheckinDoc.html*
    // @include http://southwest.com/flight/selectPrintDocument*
    // @include http://www.southwest.com/flight/retrieveCheckinDoc.html*
    // @include http://www.southwest.com/flight/selectCheckinDocDelivery.html*
    // @include http://www.southwest.com/flight/selectPrintDocument*
    // @include https://southwest.com/flight/retrieveCheckinDoc.html*
    // @include https://southwest.com/flight/selectPrintDocument*
    // @include https://www.southwest.com/flight/retrieveCheckinDoc.html*
    // @include https://www.southwest.com/flight/selectCheckinDocDelivery.html*
    // @include https://www.southwest.com/flight/selectPrintDocument*
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html

  13. @stormchasing stormchasing revised this gist Oct 1, 2014. 1 changed file with 320 additions and 320 deletions.
    640 changes: 320 additions & 320 deletions Auto Check-In to Southwest Flights.user.js
    Original file line number Diff line number Diff line change
    @@ -1,8 +1,8 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace http://www.ryanizzo.com/southwest-auto-check-in/
    // @version 1.3
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @version 1.4
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    // @description Automatically check in to Southwest Airline flights at the appropriate time.
    @@ -11,8 +11,8 @@
    // @include http://www.southwest.com/flight/retrieveCheckinDoc.html*
    // @include http://www.southwest.com/flight/selectCheckinDocDelivery.html*
    // @include http://www.southwest.com/flight/selectPrintDocument*
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html

    // ==/UserScript==
    // This program is free software: you can redistribute it and/or modify
    @@ -50,14 +50,14 @@ var globalSubmitDate;
    */
    function submitNow()
    {
    try{
    //alert(msRemaining + " " + globalSubmitDate);
    var form = document.getElementById("itineraryLookup");
    form.submit();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    try{
    //alert(msRemaining + " " + globalSubmitDate);
    var form = document.getElementById("itineraryLookup");
    form.submit();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }


    @@ -68,40 +68,40 @@ function submitNow()
    */
    function displayCountdown()
    {
    try{
    var area = document.getElementById("countdown");
    var timeRemain = globalSubmitDate - new Date();
    var days = Math.floor(timeRemain / (1000 * 60 * 60 * 24));
    var hours = Math.floor(timeRemain / (1000 * 60 * 60)) % 24;
    var minutes = Math.floor(timeRemain / (1000 * 60)) % 60;
    //round to the nearest second
    var seconds = Math.round(timeRemain / 1000) % 60;
    //Don't print negative time.
    if (hours < 0 || minutes < 0 || seconds < 0)
    {
    area.innerHTML = "Checking In...";
    return;
    }
    area.innerHTML = "Time Remaining: <strong>";
    //If 0 days remain, omit them.
    if (days != 0)
    area.innerHTML += days + "d ";
    //If 0 hours remain, omit them.
    if (hours != 0)
    area.innerHTML += hours + "h ";
    //Add padding to minute
    if (minutes !=0 )
    //area.innerHTML += "0";
    area.innerHTML += minutes + "m ";
    //Add padding to second
    //if (seconds < 10)
    //area.innerHTML += "0";
    area.innerHTML += seconds;
    area.innerHTML += "s</strong>";
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    try{
    var area = document.getElementById("countdown");
    var timeRemain = globalSubmitDate - new Date();
    var days = Math.floor(timeRemain / (1000 * 60 * 60 * 24));
    var hours = Math.floor(timeRemain / (1000 * 60 * 60)) % 24;
    var minutes = Math.floor(timeRemain / (1000 * 60)) % 60;
    //round to the nearest second
    var seconds = Math.round(timeRemain / 1000) % 60;
    //Don't print negative time.
    if (hours < 0 || minutes < 0 || seconds < 0)
    {
    area.innerHTML = "Checking In...";
    return;
    }
    area.innerHTML = "Time Remaining: <strong>";
    //If 0 days remain, omit them.
    if (days != 0)
    area.innerHTML += days + "d ";
    //If 0 hours remain, omit them.
    if (hours != 0)
    area.innerHTML += hours + "h ";
    //Add padding to minute
    if (minutes !=0 )
    //area.innerHTML += "0";
    area.innerHTML += minutes + "m ";
    //Add padding to second
    //if (seconds < 10)
    //area.innerHTML += "0";
    area.innerHTML += seconds;
    area.innerHTML += "s</strong>";
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }


    @@ -110,12 +110,12 @@ function displayCountdown()
    */
    function displayCountdownWrapper()
    {
    try{
    window.setInterval(displayCountdown, 1000);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    try{
    window.setInterval(displayCountdown, 1000);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }


    @@ -124,329 +124,329 @@ function displayCountdownWrapper()
    */
    function beginDelay()
    {
    try{
    var confNumber = document.getElementById("confirmationNumber").value;
    var firstName = document.getElementById("firstName").value;
    var lastName = document.getElementById("lastName").value;
    var month = document.getElementById("month-input").value;
    var day = document.getElementById("day-input").value;
    var year = document.getElementById("year-input").value;
    var hour = document.getElementById("hour-input").value;
    var minute = document.getElementById("minute-input").value;
    var second = document.getElementById("second-input").value;
    try{
    var confNumber = document.getElementById("confirmationNumber").value;
    var firstName = document.getElementById("firstName").value;
    var lastName = document.getElementById("lastName").value;

    var month = document.getElementById("month-input").value;
    var day = document.getElementById("day-input").value;
    var year = document.getElementById("year-input").value;

    var hour = document.getElementById("hour-input").value;
    var minute = document.getElementById("minute-input").value;
    var second = document.getElementById("second-input").value;

    var phoneArea = document.getElementById("phoneArea").value;
    var phonePrefix = document.getElementById("phonePrefix").value;
    var phoneNumber = document.getElementById("phoneNumber").value;
    if(confNumber == "" || firstName == "" || lastName == "" ){
    alert("Must fill out Confirmation Number and Name.");
    }
    else if(month == "" || month == "mm" || day == "" || day == "dd" || year == "" || year == "yyyy"
    || hour == "" || hour == "hh" || minute == "" || minute == "mm" || second == "" ){
    alert("Must fill out Date and Time.");
    }
    else if(year.length < 4 ){
    alert("Year must be 4 characters.");
    }

    if(confNumber == "" || firstName == "" || lastName == "" ){
    alert("Must fill out Confirmation Number and Name.");
    }
    else if(month == "" || month == "mm" || day == "" || day == "dd" || year == "" || year == "yyyy"
    || hour == "" || hour == "hh" || minute == "" || minute == "mm" || second == "" ){
    alert("Must fill out Date and Time.");
    }
    else if(year.length < 4 ){
    alert("Year must be 4 characters.");
    }
    else if (phoneArea.search(/\d\d\d/g) == -1 || phonePrefix.search(/\d\d\d/g) == -1 || phoneNumber.search(/\d\d\d\d/g) == -1) {
    alert("Invalid phone number provided.");
    }
    else{
    else{
    //save the text number for later
    GM_setValue("phoneArea", phoneArea);
    GM_setValue("phonePrefix", phonePrefix);
    GM_setValue("phoneNumber", phoneNumber);
    //Build a date
    var submitDate = new Date();
    //submitDate.setMonth(month - 1);
    //submitDate.setDate(day);
    submitDate.setFullYear(year, month - 1, day);
    submitDate.setHours(hour);
    submitDate.setMinutes(minute);
    submitDate.setSeconds(second);
    submitDate.setMilliseconds(0);
    var now = new Date();
    var msRemaining = submitDate - now;
    //alert(submitDate + " - " + now + " = " + msRemaining);
    var maxDays = 14;
    if(msRemaining < 0)
    alert("Date/Time must be in the future.");
    else if(msRemaining > maxDays * 1000 * 60 * 60 * 24)
    alert("Date/Time cannot be more than " + maxDays + " days in the future." + msRemaining);
    else{
    //Install the timeout to submit the form.
    window.setTimeout(submitNow, msRemaining);
    globalSubmitDate = submitDate;
    //Install a short term timeout to call the countdown wrapper at the beginning of the next second.
    window.setTimeout(displayCountdownWrapper, msRemaining % 1000);
    }
    }
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }

    //Build a date
    var submitDate = new Date();
    //submitDate.setMonth(month - 1);
    //submitDate.setDate(day);
    submitDate.setFullYear(year, month - 1, day);
    submitDate.setHours(hour);
    submitDate.setMinutes(minute);
    submitDate.setSeconds(second);
    submitDate.setMilliseconds(0);

    var now = new Date();
    var msRemaining = submitDate - now;
    //alert(submitDate + " - " + now + " = " + msRemaining);

    var maxDays = 14;
    if(msRemaining < 0)
    alert("Date/Time must be in the future.");
    else if(msRemaining > maxDays * 1000 * 60 * 60 * 24)
    alert("Date/Time cannot be more than " + maxDays + " days in the future." + msRemaining);
    else{
    //Install the timeout to submit the form.
    window.setTimeout(submitNow, msRemaining);

    globalSubmitDate = submitDate;

    //Install a short term timeout to call the countdown wrapper at the beginning of the next second.
    window.setTimeout(displayCountdownWrapper, msRemaining % 1000);
    }
    }
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }

    /**
    * @brief Edits the check in page; Adds Date, time, and Auto Check In button
    *
    * TODO Error handling. (Auto notify the developer when southwest page changes)
    */
    function checkInPageFormEdit()
    {
    try{
    var leftPanel = document.getElementsByClassName("checkIn_form_leftPanel")[0];
    //All of our stuff will go in this div.
    var delayDiv = document.createElement("div");
    delayDiv.setAttribute('id','checkInDelay');
    var dateSelect = document.createElement("span");
    dateSelect.setAttribute('id','date-select');
    //The big label at the top of the menu
    var mainLabel = document.createElement("h4");
    mainLabel.setAttribute('class','swa_feature_checkInOnline_form_header');
    mainLabel.innerHTML = "Set Check In Date and Time";
    dateSelect.innerHTML += "<br/>";
    dateSelect.appendChild(mainLabel);
    //The date portion.
    function checkInPageFormEdit()
    {
    try{
    var leftPanel = document.getElementsByClassName("checkIn_form_leftPanel")[0];

    //All of our stuff will go in this div.

    var delayDiv = document.createElement("div");
    delayDiv.setAttribute('id','checkInDelay');
    var dateSelect = document.createElement("span");
    dateSelect.setAttribute('id','date-select');

    //The big label at the top of the menu

    var mainLabel = document.createElement("h4");
    mainLabel.setAttribute('class','swa_feature_checkInOnline_form_header');
    mainLabel.innerHTML = "Set Check In Date and Time";
    dateSelect.innerHTML += "<br/>";
    dateSelect.appendChild(mainLabel);

    //The date portion.

    var today = new Date();
    var dateLabel = document.createElement("label");
    dateLabel.innerHTML = "<span class=\"required\">*</span> Date:";
    var monthInput = document.createElement("input");
    monthInput.setAttribute('id','month-input');
    monthInput.setAttribute('type','text');
    monthInput.setAttribute('maxlength','2');
    monthInput.setAttribute('size','2');
    monthInput.setAttribute('value',today.getMonth()+1);
    monthInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    monthInput.setAttribute('style','margin-left:7em');
    monthInput.setAttribute('tabindex','5');
    var dayInput = document.createElement("input");
    dayInput.setAttribute('id','day-input');
    dayInput.setAttribute('type','text');
    dayInput.setAttribute('maxlength','2');
    dayInput.setAttribute('size','2');
    dayInput.setAttribute('value',today.getDate());
    dayInput.setAttribute('onfocus','if(this.value==\'dd\') this.value=\'\';');
    dayInput.setAttribute('tabindex','6');
    var yearInput = document.createElement("input");
    yearInput.setAttribute('id','year-input');
    yearInput.setAttribute('type','text');
    yearInput.setAttribute('maxlength','4');
    yearInput.setAttribute('size','4');
    yearInput.setAttribute('value',today.getFullYear());
    yearInput.setAttribute('onfocus','if(this.value==\'yyyy\') this.value=\'\';');
    yearInput.setAttribute('tabindex','7');
    dateSelect.appendChild(dateLabel);
    dateSelect.appendChild(monthInput);
    dateSelect.innerHTML += "/";
    dateSelect.appendChild(dayInput);
    dateSelect.innerHTML += "/";
    dateSelect.appendChild(yearInput);
    // The time portion.
    var timeLabel = document.createElement("label");
    timeLabel.innerHTML = "<span class=\"required\">*</span> Time: (24-hour format) ";
    var hourInput = document.createElement("input");
    hourInput.setAttribute('id','hour-input');
    hourInput.setAttribute('type','text');
    hourInput.setAttribute('maxlength','2');
    //hourInput.setAttribute('style','margin-left:10px');
    hourInput.setAttribute('size','2');
    hourInput.setAttribute('value',today.getHours());
    hourInput.setAttribute('onfocus','if(this.value==\'hh\') this.value=\'\';');
    hourInput.setAttribute('tabindex','8');
    var minuteInput = document.createElement("input");
    minuteInput.setAttribute('id','minute-input');
    minuteInput.setAttribute('type','text');
    minuteInput.setAttribute('maxlength','2');
    minuteInput.setAttribute('size','2');
    minuteInput.setAttribute('value',today.getMinutes());
    minuteInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    minuteInput.setAttribute('tabindex','9');
    var secondInput = document.createElement("input");
    secondInput.setAttribute('id','second-input');
    secondInput.setAttribute('type','text');
    secondInput.setAttribute('maxlength','2');
    secondInput.setAttribute('size','2');
    secondInput.setAttribute('value','02');
    secondInput.setAttribute('tabindex','10');
    dateSelect.innerHTML += "<br/><br/>";
    dateSelect.appendChild(timeLabel);
    dateSelect.appendChild(hourInput);
    dateSelect.innerHTML += ":";
    dateSelect.appendChild(minuteInput);
    dateSelect.innerHTML += ":";
    dateSelect.appendChild(secondInput);
    delayDiv.appendChild(dateSelect);


    var dateLabel = document.createElement("label");
    dateLabel.innerHTML = "<span class=\"required\">*</span> Date:";

    var monthInput = document.createElement("input");
    monthInput.setAttribute('id','month-input');
    monthInput.setAttribute('type','text');
    monthInput.setAttribute('maxlength','2');
    monthInput.setAttribute('size','2');
    monthInput.setAttribute('value',today.getMonth()+1);
    monthInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    monthInput.setAttribute('style','margin-left:7em');
    monthInput.setAttribute('tabindex','5');

    var dayInput = document.createElement("input");
    dayInput.setAttribute('id','day-input');
    dayInput.setAttribute('type','text');
    dayInput.setAttribute('maxlength','2');
    dayInput.setAttribute('size','2');
    dayInput.setAttribute('value',today.getDate());
    dayInput.setAttribute('onfocus','if(this.value==\'dd\') this.value=\'\';');
    dayInput.setAttribute('tabindex','6');

    var yearInput = document.createElement("input");
    yearInput.setAttribute('id','year-input');
    yearInput.setAttribute('type','text');
    yearInput.setAttribute('maxlength','4');
    yearInput.setAttribute('size','4');
    yearInput.setAttribute('value',today.getFullYear());
    yearInput.setAttribute('onfocus','if(this.value==\'yyyy\') this.value=\'\';');
    yearInput.setAttribute('tabindex','7');

    dateSelect.appendChild(dateLabel);
    dateSelect.appendChild(monthInput);
    dateSelect.innerHTML += "/";
    dateSelect.appendChild(dayInput);
    dateSelect.innerHTML += "/";
    dateSelect.appendChild(yearInput);

    // The time portion.

    var timeLabel = document.createElement("label");
    timeLabel.innerHTML = "<span class=\"required\">*</span> Time: (24-hour format) ";

    var hourInput = document.createElement("input");
    hourInput.setAttribute('id','hour-input');
    hourInput.setAttribute('type','text');
    hourInput.setAttribute('maxlength','2');
    //hourInput.setAttribute('style','margin-left:10px');
    hourInput.setAttribute('size','2');
    hourInput.setAttribute('value',today.getHours());
    hourInput.setAttribute('onfocus','if(this.value==\'hh\') this.value=\'\';');
    hourInput.setAttribute('tabindex','8');

    var minuteInput = document.createElement("input");
    minuteInput.setAttribute('id','minute-input');
    minuteInput.setAttribute('type','text');
    minuteInput.setAttribute('maxlength','2');
    minuteInput.setAttribute('size','2');
    minuteInput.setAttribute('value',today.getMinutes());
    minuteInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    minuteInput.setAttribute('tabindex','9');

    var secondInput = document.createElement("input");
    secondInput.setAttribute('id','second-input');
    secondInput.setAttribute('type','text');
    secondInput.setAttribute('maxlength','2');
    secondInput.setAttribute('size','2');
    secondInput.setAttribute('value','02');
    secondInput.setAttribute('tabindex','10');

    dateSelect.innerHTML += "<br/><br/>";

    dateSelect.appendChild(timeLabel);
    dateSelect.appendChild(hourInput);
    dateSelect.innerHTML += ":";
    dateSelect.appendChild(minuteInput);
    dateSelect.innerHTML += ":";
    dateSelect.appendChild(secondInput);

    delayDiv.appendChild(dateSelect);

    //auto-text boarding pass section
    var autoTextArea = document.createElement("div");
    var textLabel = document.createElement("label");
    textLabel.innerHTML = "<span class=\"required\">*</span> Boarding pass text number: ";
    var phoneArea = document.createElement("input");
    phoneArea.setAttribute('id','phoneArea');
    phoneArea.setAttribute('type','text');
    phoneArea.setAttribute('maxlength','3');
    phoneArea.setAttribute('size','3');
    var autoTextArea = document.createElement("div");
    var textLabel = document.createElement("label");
    textLabel.innerHTML = "<span class=\"required\">*</span> Boarding pass text number: ";

    var phoneArea = document.createElement("input");
    phoneArea.setAttribute('id','phoneArea');
    phoneArea.setAttribute('type','text');
    phoneArea.setAttribute('maxlength','3');
    phoneArea.setAttribute('size','3');
    phoneArea.setAttribute('value', GM_getValue("phoneArea") != undefined ? GM_getValue("phoneArea") : '');
    phoneArea.setAttribute('tabindex','12');
    var phonePrefix = document.createElement("input");
    phonePrefix.setAttribute('id','phonePrefix');
    phonePrefix.setAttribute('type','text');
    phonePrefix.setAttribute('maxlength','3');
    phonePrefix.setAttribute('size','3');
    phonePrefix.setAttribute('value', GM_getValue("phonePrefix") != undefined ? GM_getValue("phonePrefix") : '');
    phonePrefix.setAttribute('tabindex','13');
    var phoneNumber = document.createElement("input");
    phoneNumber.setAttribute('id','phoneNumber');
    phoneNumber.setAttribute('type','text');
    phoneNumber.setAttribute('maxlength','4');
    phoneNumber.setAttribute('size','4');
    phoneNumber.setAttribute('value', GM_getValue("phoneNumber") != undefined ? GM_getValue("phoneNumber") : '');
    phoneNumber.setAttribute('tabindex','14');
    autoTextArea.innerHTML += "<br/>";
    autoTextArea.appendChild(textLabel);
    phoneArea.setAttribute('tabindex','12');

    var phonePrefix = document.createElement("input");
    phonePrefix.setAttribute('id','phonePrefix');
    phonePrefix.setAttribute('type','text');
    phonePrefix.setAttribute('maxlength','3');
    phonePrefix.setAttribute('size','3');
    phonePrefix.setAttribute('value', GM_getValue("phonePrefix") != undefined ? GM_getValue("phonePrefix") : '');
    phonePrefix.setAttribute('tabindex','13');

    var phoneNumber = document.createElement("input");
    phoneNumber.setAttribute('id','phoneNumber');
    phoneNumber.setAttribute('type','text');
    phoneNumber.setAttribute('maxlength','4');
    phoneNumber.setAttribute('size','4');
    phoneNumber.setAttribute('value', GM_getValue("phoneNumber") != undefined ? GM_getValue("phoneNumber") : '');
    phoneNumber.setAttribute('tabindex','14');

    autoTextArea.innerHTML += "<br/>";

    autoTextArea.appendChild(textLabel);
    autoTextArea.innerHTML += "(";
    autoTextArea.appendChild(phoneArea);
    autoTextArea.innerHTML += ")";
    autoTextArea.appendChild(phonePrefix);
    autoTextArea.innerHTML += "-";
    autoTextArea.appendChild(phoneNumber);
    delayDiv.appendChild(autoTextArea);
    delayDiv.innerHTML += "<br/><br />";
    // The area that displays how much time remains before the form is submitted.
    var countdownArea = document.createElement("div");
    countdownArea.setAttribute('id','countdown');
    countdownArea.innerHTML = "Click to start countdown";
    delayDiv.appendChild(countdownArea);
    // Auto Check In button
    var delayButton = document.createElement("input");
    delayButton.setAttribute('id','delay-button');
    delayButton.setAttribute('type','button');
    delayButton.setAttribute('style','float: right; background-color: #FF3300; color: white');
    delayButton.setAttribute('value','Auto Check In');
    delayButton.addEventListener("click", beginDelay, true);
    delayButton.setAttribute('tabindex','11');
    delayDiv.appendChild(delayButton);
    leftPanel.appendChild(delayDiv);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    autoTextArea.appendChild(phoneArea);
    autoTextArea.innerHTML += ")";
    autoTextArea.appendChild(phonePrefix);
    autoTextArea.innerHTML += "-";
    autoTextArea.appendChild(phoneNumber);

    delayDiv.appendChild(autoTextArea);

    delayDiv.innerHTML += "<br/><br />";

    // The area that displays how much time remains before the form is submitted.

    var countdownArea = document.createElement("div");
    countdownArea.setAttribute('id','countdown');
    countdownArea.innerHTML = "Click to start countdown";

    delayDiv.appendChild(countdownArea);

    // Auto Check In button

    var delayButton = document.createElement("input");
    delayButton.setAttribute('id','delay-button');
    delayButton.setAttribute('type','button');
    delayButton.setAttribute('style','float: right; background-color: #FF3300; color: white');
    delayButton.setAttribute('value','Auto Check In');
    delayButton.addEventListener("click", beginDelay, true);
    delayButton.setAttribute('tabindex','11');

    delayDiv.appendChild(delayButton);

    leftPanel.appendChild(delayDiv);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }

    ///////////// SELECT PASSENGER PAGE ////////////////

    //automatically select all passengers and submit the form
    function autoPassengerPage()
    {
    try{
    //find error notification
    if(document.title == "Error")
    return;
    // Check all the check boxes.
    var node_list = document.getElementsByTagName('input');
    for (var i = 0; i < node_list.length; i++) {
    var node = node_list[i];
    if (node.getAttribute('type') == 'checkbox') {
    node.checked = true;
    }
    }
    //Click the print button
    var button = document.getElementById("printDocumentsButton");
    button.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    try{
    //find error notification
    if(document.title == "Error")
    return;

    // Check all the check boxes.
    var node_list = document.getElementsByTagName('input');
    for (var i = 0; i < node_list.length; i++) {
    var node = node_list[i];
    if (node.getAttribute('type') == 'checkbox') {
    node.checked = true;
    }
    }

    //Click the print button
    var button = document.getElementById("printDocumentsButton");
    button.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }

    }

    ///////////// BOARDING DOC DELIVERY PAGE ////////////////

    function autoTextBoardingDocs()
    {
    try{
    //find error notification
    if (document.title == "Error")
    return;
    try{
    //find error notification
    if (document.title == "Error")
    return;

    //check the Text checkbox if it's there
    var textCheckbox = document.getElementById("optionText1");
    if (textCheckbox == null || !GM_getValue("phoneArea") || !GM_getValue("phonePrefix") || !GM_getValue("phoneNumber"))
    return;
    textCheckbox.checked = "checked";

    //fill the mobile number
    var phoneArea = document.getElementById("phoneArea").value = GM_getValue( "phoneArea");
    var phonePrefix = document.getElementById("phonePrefix").value = GM_getValue("phonePrefix");
    var phoneNumber = document.getElementById("phoneNumber").value = GM_getValue("phoneNumber");
    //Click the continue button
    var button = document.getElementById("checkin_button");
    button.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }

    //Click the continue button
    var button = document.getElementById("checkin_button");
    button.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }

    }

    //case of the select boarding pass page (regex match the url)
    if(/selectPrintDocument/.test(document.location.href))
    {
    autoPassengerPage();
    autoPassengerPage();
    }
    //case of the check in page
    else if(/retrieveCheckinDoc/.test(document.location.href))
    {
    checkInPageFormEdit();
    checkInPageFormEdit();
    }
    else if(/selectCheckinDocDelivery/.test(document.location.href))
    {
    autoTextBoardingDocs();
    autoTextBoardingDocs();
    }

  14. @stormchasing stormchasing created this gist Oct 1, 2014.
    452 changes: 452 additions & 0 deletions Auto Check-In to Southwest Flights.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,452 @@
    // ==UserScript==
    // @name Auto Check-In to Southwest Flights
    // @namespace http://www.ryanizzo.com/southwest-auto-check-in/
    // @version 1.3
    // @author Nicholas Buroojy (http://userscripts.org/users/83813)
    // @contributor Ryan Izzo (http://www.ryanizzo.com)
    // @contributor JR Hehnly (http://www.okstorms.com @stormchasing)
    // @description Automatically check in to Southwest Airline flights at the appropriate time.
    // @include http://southwest.com/flight/retrieveCheckinDoc.html*
    // @include http://southwest.com/flight/selectPrintDocument*
    // @include http://www.southwest.com/flight/retrieveCheckinDoc.html*
    // @include http://www.southwest.com/flight/selectCheckinDocDelivery.html*
    // @include http://www.southwest.com/flight/selectPrintDocument*
    // @copyright 2009+, Nicholas Buroojy (http://userscripts.org/users/83813)
    // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html

    // ==/UserScript==
    // This program is free software: you can redistribute it and/or modify
    // it under the terms of the GNU General Public License as published by
    // the Free Software Foundation, either version 3 of the License, or
    // (at your option) any later version.
    //
    // This program is distributed in the hope that it will be useful,
    // but WITHOUT ANY WARRANTY; without even the implied warranty of
    // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    // GNU General Public License for more details.
    // You should have received a copy of the GNU General Public License
    // along with this program. If not, see <http://www.gnu.org/licenses/>.
    //
    // History
    //
    // 10/2012 v1.2 Ryan Izzo (ryanizzo.com)
    // Updated to use new Southwest Check In page, added validation
    //
    // 7/2014 v1.3 Ryan Izzo (ryanizzo.com)
    // Moved script to GitHub since UserScripts appears dead
    //
    // 10/2014 v1.4 JR Hehnly (okstorms.com)
    // Added phone number entry to auto-text boarding pass docs to mobile device
    //
    // TODO: Use Southwest's server's time instead of the client's clock.
    // TODO: Test select passenger page.

    ///////////// CHECK IN PAGE ////////////////

    var globalSubmitDate;

    /**
    * @brief Submit the check in form on the Southwest Check In Online page.
    */
    function submitNow()
    {
    try{
    //alert(msRemaining + " " + globalSubmitDate);
    var form = document.getElementById("itineraryLookup");
    form.submit();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }


    /**
    * @brief Display the countdown.
    *
    * TODO: Some formatting is wrong eg ("1:0:12" means 1 hour and 12 seconds remain). Make sure everything is represented with 2 digits.
    */
    function displayCountdown()
    {
    try{
    var area = document.getElementById("countdown");
    var timeRemain = globalSubmitDate - new Date();
    var days = Math.floor(timeRemain / (1000 * 60 * 60 * 24));
    var hours = Math.floor(timeRemain / (1000 * 60 * 60)) % 24;
    var minutes = Math.floor(timeRemain / (1000 * 60)) % 60;
    //round to the nearest second
    var seconds = Math.round(timeRemain / 1000) % 60;
    //Don't print negative time.
    if (hours < 0 || minutes < 0 || seconds < 0)
    {
    area.innerHTML = "Checking In...";
    return;
    }
    area.innerHTML = "Time Remaining: <strong>";
    //If 0 days remain, omit them.
    if (days != 0)
    area.innerHTML += days + "d ";
    //If 0 hours remain, omit them.
    if (hours != 0)
    area.innerHTML += hours + "h ";
    //Add padding to minute
    if (minutes !=0 )
    //area.innerHTML += "0";
    area.innerHTML += minutes + "m ";
    //Add padding to second
    //if (seconds < 10)
    //area.innerHTML += "0";
    area.innerHTML += seconds;
    area.innerHTML += "s</strong>";
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }


    /**
    * @brief Updates the countdown every second.
    */
    function displayCountdownWrapper()
    {
    try{
    window.setInterval(displayCountdown, 1000);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }


    /**
    * @brief Begins the delay at the next even second.
    */
    function beginDelay()
    {
    try{
    var confNumber = document.getElementById("confirmationNumber").value;
    var firstName = document.getElementById("firstName").value;
    var lastName = document.getElementById("lastName").value;

    var month = document.getElementById("month-input").value;
    var day = document.getElementById("day-input").value;
    var year = document.getElementById("year-input").value;

    var hour = document.getElementById("hour-input").value;
    var minute = document.getElementById("minute-input").value;
    var second = document.getElementById("second-input").value;

    var phoneArea = document.getElementById("phoneArea").value;
    var phonePrefix = document.getElementById("phonePrefix").value;
    var phoneNumber = document.getElementById("phoneNumber").value;

    if(confNumber == "" || firstName == "" || lastName == "" ){
    alert("Must fill out Confirmation Number and Name.");
    }
    else if(month == "" || month == "mm" || day == "" || day == "dd" || year == "" || year == "yyyy"
    || hour == "" || hour == "hh" || minute == "" || minute == "mm" || second == "" ){
    alert("Must fill out Date and Time.");
    }
    else if(year.length < 4 ){
    alert("Year must be 4 characters.");
    }
    else if (phoneArea.search(/\d\d\d/g) == -1 || phonePrefix.search(/\d\d\d/g) == -1 || phoneNumber.search(/\d\d\d\d/g) == -1) {
    alert("Invalid phone number provided.");
    }
    else{
    //save the text number for later
    GM_setValue("phoneArea", phoneArea);
    GM_setValue("phonePrefix", phonePrefix);
    GM_setValue("phoneNumber", phoneNumber);

    //Build a date
    var submitDate = new Date();
    //submitDate.setMonth(month - 1);
    //submitDate.setDate(day);
    submitDate.setFullYear(year, month - 1, day);
    submitDate.setHours(hour);
    submitDate.setMinutes(minute);
    submitDate.setSeconds(second);
    submitDate.setMilliseconds(0);

    var now = new Date();
    var msRemaining = submitDate - now;
    //alert(submitDate + " - " + now + " = " + msRemaining);

    var maxDays = 14;
    if(msRemaining < 0)
    alert("Date/Time must be in the future.");
    else if(msRemaining > maxDays * 1000 * 60 * 60 * 24)
    alert("Date/Time cannot be more than " + maxDays + " days in the future." + msRemaining);
    else{
    //Install the timeout to submit the form.
    window.setTimeout(submitNow, msRemaining);

    globalSubmitDate = submitDate;

    //Install a short term timeout to call the countdown wrapper at the beginning of the next second.
    window.setTimeout(displayCountdownWrapper, msRemaining % 1000);
    }
    }
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }

    /**
    * @brief Edits the check in page; Adds Date, time, and Auto Check In button
    *
    * TODO Error handling. (Auto notify the developer when southwest page changes)
    */
    function checkInPageFormEdit()
    {
    try{
    var leftPanel = document.getElementsByClassName("checkIn_form_leftPanel")[0];

    //All of our stuff will go in this div.

    var delayDiv = document.createElement("div");
    delayDiv.setAttribute('id','checkInDelay');
    var dateSelect = document.createElement("span");
    dateSelect.setAttribute('id','date-select');

    //The big label at the top of the menu

    var mainLabel = document.createElement("h4");
    mainLabel.setAttribute('class','swa_feature_checkInOnline_form_header');
    mainLabel.innerHTML = "Set Check In Date and Time";
    dateSelect.innerHTML += "<br/>";
    dateSelect.appendChild(mainLabel);

    //The date portion.

    var today = new Date();


    var dateLabel = document.createElement("label");
    dateLabel.innerHTML = "<span class=\"required\">*</span> Date:";

    var monthInput = document.createElement("input");
    monthInput.setAttribute('id','month-input');
    monthInput.setAttribute('type','text');
    monthInput.setAttribute('maxlength','2');
    monthInput.setAttribute('size','2');
    monthInput.setAttribute('value',today.getMonth()+1);
    monthInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    monthInput.setAttribute('style','margin-left:7em');
    monthInput.setAttribute('tabindex','5');

    var dayInput = document.createElement("input");
    dayInput.setAttribute('id','day-input');
    dayInput.setAttribute('type','text');
    dayInput.setAttribute('maxlength','2');
    dayInput.setAttribute('size','2');
    dayInput.setAttribute('value',today.getDate());
    dayInput.setAttribute('onfocus','if(this.value==\'dd\') this.value=\'\';');
    dayInput.setAttribute('tabindex','6');

    var yearInput = document.createElement("input");
    yearInput.setAttribute('id','year-input');
    yearInput.setAttribute('type','text');
    yearInput.setAttribute('maxlength','4');
    yearInput.setAttribute('size','4');
    yearInput.setAttribute('value',today.getFullYear());
    yearInput.setAttribute('onfocus','if(this.value==\'yyyy\') this.value=\'\';');
    yearInput.setAttribute('tabindex','7');

    dateSelect.appendChild(dateLabel);
    dateSelect.appendChild(monthInput);
    dateSelect.innerHTML += "/";
    dateSelect.appendChild(dayInput);
    dateSelect.innerHTML += "/";
    dateSelect.appendChild(yearInput);

    // The time portion.

    var timeLabel = document.createElement("label");
    timeLabel.innerHTML = "<span class=\"required\">*</span> Time: (24-hour format) ";

    var hourInput = document.createElement("input");
    hourInput.setAttribute('id','hour-input');
    hourInput.setAttribute('type','text');
    hourInput.setAttribute('maxlength','2');
    //hourInput.setAttribute('style','margin-left:10px');
    hourInput.setAttribute('size','2');
    hourInput.setAttribute('value',today.getHours());
    hourInput.setAttribute('onfocus','if(this.value==\'hh\') this.value=\'\';');
    hourInput.setAttribute('tabindex','8');

    var minuteInput = document.createElement("input");
    minuteInput.setAttribute('id','minute-input');
    minuteInput.setAttribute('type','text');
    minuteInput.setAttribute('maxlength','2');
    minuteInput.setAttribute('size','2');
    minuteInput.setAttribute('value',today.getMinutes());
    minuteInput.setAttribute('onfocus','if(this.value==\'mm\') this.value=\'\';');
    minuteInput.setAttribute('tabindex','9');

    var secondInput = document.createElement("input");
    secondInput.setAttribute('id','second-input');
    secondInput.setAttribute('type','text');
    secondInput.setAttribute('maxlength','2');
    secondInput.setAttribute('size','2');
    secondInput.setAttribute('value','02');
    secondInput.setAttribute('tabindex','10');

    dateSelect.innerHTML += "<br/><br/>";

    dateSelect.appendChild(timeLabel);
    dateSelect.appendChild(hourInput);
    dateSelect.innerHTML += ":";
    dateSelect.appendChild(minuteInput);
    dateSelect.innerHTML += ":";
    dateSelect.appendChild(secondInput);

    delayDiv.appendChild(dateSelect);

    //auto-text boarding pass section
    var autoTextArea = document.createElement("div");
    var textLabel = document.createElement("label");
    textLabel.innerHTML = "<span class=\"required\">*</span> Boarding pass text number: ";

    var phoneArea = document.createElement("input");
    phoneArea.setAttribute('id','phoneArea');
    phoneArea.setAttribute('type','text');
    phoneArea.setAttribute('maxlength','3');
    phoneArea.setAttribute('size','3');
    phoneArea.setAttribute('value', GM_getValue("phoneArea") != undefined ? GM_getValue("phoneArea") : '');
    phoneArea.setAttribute('tabindex','12');

    var phonePrefix = document.createElement("input");
    phonePrefix.setAttribute('id','phonePrefix');
    phonePrefix.setAttribute('type','text');
    phonePrefix.setAttribute('maxlength','3');
    phonePrefix.setAttribute('size','3');
    phonePrefix.setAttribute('value', GM_getValue("phonePrefix") != undefined ? GM_getValue("phonePrefix") : '');
    phonePrefix.setAttribute('tabindex','13');

    var phoneNumber = document.createElement("input");
    phoneNumber.setAttribute('id','phoneNumber');
    phoneNumber.setAttribute('type','text');
    phoneNumber.setAttribute('maxlength','4');
    phoneNumber.setAttribute('size','4');
    phoneNumber.setAttribute('value', GM_getValue("phoneNumber") != undefined ? GM_getValue("phoneNumber") : '');
    phoneNumber.setAttribute('tabindex','14');

    autoTextArea.innerHTML += "<br/>";

    autoTextArea.appendChild(textLabel);
    autoTextArea.innerHTML += "(";
    autoTextArea.appendChild(phoneArea);
    autoTextArea.innerHTML += ")";
    autoTextArea.appendChild(phonePrefix);
    autoTextArea.innerHTML += "-";
    autoTextArea.appendChild(phoneNumber);

    delayDiv.appendChild(autoTextArea);

    delayDiv.innerHTML += "<br/><br />";

    // The area that displays how much time remains before the form is submitted.

    var countdownArea = document.createElement("div");
    countdownArea.setAttribute('id','countdown');
    countdownArea.innerHTML = "Click to start countdown";

    delayDiv.appendChild(countdownArea);

    // Auto Check In button

    var delayButton = document.createElement("input");
    delayButton.setAttribute('id','delay-button');
    delayButton.setAttribute('type','button');
    delayButton.setAttribute('style','float: right; background-color: #FF3300; color: white');
    delayButton.setAttribute('value','Auto Check In');
    delayButton.addEventListener("click", beginDelay, true);
    delayButton.setAttribute('tabindex','11');

    delayDiv.appendChild(delayButton);

    leftPanel.appendChild(delayDiv);
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }
    }

    ///////////// SELECT PASSENGER PAGE ////////////////

    //automatically select all passengers and submit the form
    function autoPassengerPage()
    {
    try{
    //find error notification
    if(document.title == "Error")
    return;

    // Check all the check boxes.
    var node_list = document.getElementsByTagName('input');
    for (var i = 0; i < node_list.length; i++) {
    var node = node_list[i];
    if (node.getAttribute('type') == 'checkbox') {
    node.checked = true;
    }
    }

    //Click the print button
    var button = document.getElementById("printDocumentsButton");
    button.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }

    }

    ///////////// BOARDING DOC DELIVERY PAGE ////////////////

    function autoTextBoardingDocs()
    {
    try{
    //find error notification
    if (document.title == "Error")
    return;

    //check the Text checkbox if it's there
    var textCheckbox = document.getElementById("optionText1");
    if (textCheckbox == null || !GM_getValue("phoneArea") || !GM_getValue("phonePrefix") || !GM_getValue("phoneNumber"))
    return;
    textCheckbox.checked = "checked";

    //fill the mobile number
    var phoneArea = document.getElementById("phoneArea").value = GM_getValue( "phoneArea");
    var phonePrefix = document.getElementById("phonePrefix").value = GM_getValue("phonePrefix");
    var phoneNumber = document.getElementById("phoneNumber").value = GM_getValue("phoneNumber");

    //Click the continue button
    var button = document.getElementById("checkin_button");
    button.click();
    }
    catch(e){
    alert('An error has occurred: '+e.message);
    }

    }

    //case of the select boarding pass page (regex match the url)
    if(/selectPrintDocument/.test(document.location.href))
    {
    autoPassengerPage();
    }
    //case of the check in page
    else if(/retrieveCheckinDoc/.test(document.location.href))
    {
    checkInPageFormEdit();
    }
    else if(/selectCheckinDocDelivery/.test(document.location.href))
    {
    autoTextBoardingDocs();
    }