Skip to content

Instantly share code, notes, and snippets.

@3rdcycle
Forked from weiserr/README.md
Created April 26, 2018 17:48
Show Gist options
  • Select an option

  • Save 3rdcycle/fb057183c22dc1164664a248df011604 to your computer and use it in GitHub Desktop.

Select an option

Save 3rdcycle/fb057183c22dc1164664a248df011604 to your computer and use it in GitHub Desktop.

Revisions

  1. @weiserr weiserr revised this gist Sep 16, 2017. 1 changed file with 10 additions and 16 deletions.
    26 changes: 10 additions & 16 deletions postfinance-ynab.user.js
    Original file line number Diff line number Diff line change
    @@ -2,27 +2,19 @@
    // @name Postfinance CSV Export
    // @namespace http://death-knight.com
    // @include https://www.postfinance.ch/ap/ba/fp/html/e-finance/assets
    // @version 3
    // @version 4
    // @grant none
    // ==/UserScript==
    // Function definitions
    function initializeYnabExport() {
    // adapt the name of the standard export button
    $("button", $("input[name='data']")[0].parentNode)[0].textContent = "1. Export";

    // add the generation button
    createGenerateButton();
    }

    function createGenerateButton() {
    let input = document.createElement("input");
    input.type = "button";
    input.value = "2. YNAB Generate";
    input.value = "YNAB Export";
    input.className = "btn";
    input.style.setProperty('margin-left', '8px');
    input.onclick = createExportButton;

    $("input[name='filename']")[0].parentNode.append(input);
    $("input[name='data']")[0].parentNode.append(input);
    }

    function createExportButton() {
    @@ -33,14 +25,16 @@ function createExportButton() {
    const day = date.getDate();
    const filename = "ynab-" + year + "-" + month + "-" + day + ".csv";

    // create a temporary download link
    let input = document.createElement("a");
    input.setAttribute('href', 'data:text/csv;charset=UTF-8,' + encodeURIComponent(csv));
    input.innerHTML = "3. YNAB Export";
    input.className = "btn";
    input.style.setProperty('margin-left', '8px');
    input.setAttribute('download', filename);
    input.style.display = 'none';

    $("input[name='filename']")[0].parentNode.append(input);
    // ...and click it to trigger the download
    document.body.appendChild(input);
    input.click();
    document.body.removeChild(input);
    }

    function createCSV() {
    @@ -154,4 +148,4 @@ function waitForKeyElements(
    }

    // Main entry point
    waitForKeyElements("input[name='data']", initializeYnabExport);
    waitForKeyElements("input[name='data']", createGenerateButton);
  2. @weiserr weiserr revised this gist Sep 16, 2017. 1 changed file with 4 additions and 5 deletions.
    9 changes: 4 additions & 5 deletions postfinance-ynab.user.js
    Original file line number Diff line number Diff line change
    @@ -58,14 +58,13 @@ function createHeader() {
    return 'Date,Payee,Category,Memo,Outflow,Inflow';
    }

    // TODO: properly sanitize and sort the values
    function sanitizeRow(row) {
    const date = row[0];
    const payee = row[1];
    const date = row[0].replace(/(.*)-(.*)-(.*)/, '$3.$2.$1');
    const payee = row[1].replace(/\"/gi, '');
    const category = '';
    const memo = '';
    const outflow = row[3];
    const inflow = '';
    const outflow = row[3].replace(/-(.*)/, '$1-');
    const inflow = row[2];

    let line = [];
    line.push(date);
  3. @weiserr weiserr revised this gist Sep 16, 2017. 1 changed file with 92 additions and 87 deletions.
    179 changes: 92 additions & 87 deletions postfinance-ynab.user.js
    Original file line number Diff line number Diff line change
    @@ -6,76 +6,82 @@
    // @grant none
    // ==/UserScript==
    // Function definitions
    function createAndAppendButton() {
    var input=document.createElement("input");
    input.type="button";
    input.value="Generate CSV Link";
    input.className="efinance-button";
    input.onclick = provideCSVLink;
    $("p.buttons").append(input);
    function initializeYnabExport() {
    // adapt the name of the standard export button
    $("button", $("input[name='data']")[0].parentNode)[0].textContent = "1. Export";

    // add the generation button
    createGenerateButton();
    }

    function provideCSVLink() {
    var input=document.createElement("a");
    var csv = createCSV();
    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    var filename = "ynab-" + year + "-" + month + "-" + day + ".csv";

    input.setAttribute('href','data:text/csv;charset=UTF-8,' + encodeURIComponent(csv));
    input.innerHTML = "Export to CSV";
    input.className="efinance-button";
    input.setAttribute('download',filename);

    $("p.buttons").append(input);
    function createGenerateButton() {
    let input = document.createElement("input");
    input.type = "button";
    input.value = "2. YNAB Generate";
    input.className = "btn";
    input.style.setProperty('margin-left', '8px');
    input.onclick = createExportButton;

    $("input[name='filename']")[0].parentNode.append(input);
    }

    function createExportButton() {
    const csv = createCSV();
    const date = new Date();
    const year = date.getFullYear();
    const month = date.getMonth() + 1;
    const day = date.getDate();
    const filename = "ynab-" + year + "-" + month + "-" + day + ".csv";

    let input = document.createElement("a");
    input.setAttribute('href', 'data:text/csv;charset=UTF-8,' + encodeURIComponent(csv));
    input.innerHTML = "3. YNAB Export";
    input.className = "btn";
    input.style.setProperty('margin-left', '8px');
    input.setAttribute('download', filename);

    $("input[name='filename']")[0].parentNode.append(input);
    }

    function createCSV() {
    var result = [];
    var lines = $("tbody").children("#detail_page tr");

    // push the header
    result.push('Date,Payee,Category,Memo,Outflow,Inflow');

    lines.each(function(){appendCreditDebitLine($(this),result)});

    return result.join("\n");
    // acquire the data computed by the Post
    let result = JSON.parse($("input[name='data']")[0].value)

    // process the content
    result = result.filter(row => row.length === 6).map((row, index) => index > 0 ? sanitizeRow(row) : createHeader());

    // join the results into a single string
    return result.join("\n");
    }

    // Date,Payee,Category,Memo,Outflow,Inflow
    function appendCreditDebitLine(context, lines) {
    var line = [];
    var cells = context.children("td");
    var date = sanitize(cells.get(5));
    var payee = "";
    var category = "";
    var memo = sanitize(cells.get(2));
    var outflow = sanitize(cells.get(4));
    var inflow = sanitize(cells.get(3));


    // create a CSV line
    line.push(date);
    line.push(payee);
    line.push(category);
    line.push(memo);
    line.push(outflow);
    line.push(inflow);

    // append the CSV line
    lines.push(line.join(","));
    function createHeader() {
    return 'Date,Payee,Category,Memo,Outflow,Inflow';
    }

    function sanitize(cell) {
    return cell.innerHTML.replace(/<br>/gi," ").replace(/&nbsp;/gi,"").replace(/'/gi,'').trimLeft().trimRight()
    // TODO: properly sanitize and sort the values
    function sanitizeRow(row) {
    const date = row[0];
    const payee = row[1];
    const category = '';
    const memo = '';
    const outflow = row[3];
    const inflow = '';

    let line = [];
    line.push(date);
    line.push(payee);
    line.push(category);
    line.push(memo);
    line.push(outflow);
    line.push(inflow);

    return line.join(',');
    }

    /* waitForKeyElements(): A handy, utility function that
    * does what it says.
    */
    function waitForKeyElements (
    function waitForKeyElements(
    selectorTxt, /* Required: The jQuery selector string that
    specifies the desired element(s).
    */
    @@ -90,64 +96,63 @@ function waitForKeyElements (
    iframeSelector /* Optional: If set, identifies the iframe to
    search.
    */
    )
    {
    ) {
    var targetNodes, btargetsFound;

    if (typeof iframeSelector == "undefined")
    targetNodes = $(selectorTxt);
    targetNodes = $(selectorTxt);
    else
    targetNodes = $(iframeSelector).contents ()
    .find (selectorTxt);
    targetNodes = $(iframeSelector).contents()
    .find(selectorTxt);

    if (targetNodes && targetNodes.length > 0) {
    if (targetNodes && targetNodes.length > 0) {
    /*--- Found target node(s). Go through each and act if they
    are new.
    */
    targetNodes.each ( function () {
    var jThis = $(this);
    var alreadyFound = jThis.data ('alreadyFound') || false;
    targetNodes.each(function () {
    var jThis = $(this);
    var alreadyFound = jThis.data('alreadyFound') || false;

    if (!alreadyFound) {
    //--- Call the payload function.
    actionFunction (jThis);
    jThis.data ('alreadyFound', true);
    actionFunction(jThis);
    jThis.data('alreadyFound', true);
    }
    } );
    btargetsFound = true;
    });
    btargetsFound = true;
    }
    else {
    btargetsFound = false;
    btargetsFound = false;
    }

    //--- Get the timer-control variable for this selector.
    var controlObj = waitForKeyElements.controlObj || {};
    var controlKey = selectorTxt.replace (/[^\w]/g, "_");
    var timeControl = controlObj [controlKey];
    var controlObj = waitForKeyElements.controlObj || {};
    var controlKey = selectorTxt.replace(/[^\w]/g, "_");
    var timeControl = controlObj[controlKey];

    //--- Now set or clear the timer as appropriate.
    if (btargetsFound && bWaitOnce && timeControl) {
    if (btargetsFound && bWaitOnce && timeControl) {
    //--- The only condition where we need to clear the timer.
    clearInterval (timeControl);
    delete controlObj [controlKey]
    clearInterval(timeControl);
    delete controlObj[controlKey]
    }
    else {
    //--- Set a timer, if needed.
    if ( ! timeControl) {
    timeControl = setInterval ( function () {
    waitForKeyElements ( selectorTxt,
    actionFunction,
    bWaitOnce,
    iframeSelector
    );
    },
    if (!timeControl) {
    timeControl = setInterval(function () {
    waitForKeyElements(selectorTxt,
    actionFunction,
    bWaitOnce,
    iframeSelector
    );
    },
    500
    );
    controlObj [controlKey] = timeControl;
    controlObj[controlKey] = timeControl;
    }
    }
    waitForKeyElements.controlObj = controlObj;
    waitForKeyElements.controlObj = controlObj;
    }

    // Main entry point
    waitForKeyElements ("p.buttons", createAndAppendButton);
    waitForKeyElements("input[name='data']", initializeYnabExport);
  4. @weiserr weiserr created this gist Dec 28, 2015.
    153 changes: 153 additions & 0 deletions postfinance-ynab.user.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,153 @@
    // ==UserScript==
    // @name Postfinance CSV Export
    // @namespace http://death-knight.com
    // @include https://www.postfinance.ch/ap/ba/fp/html/e-finance/assets
    // @version 3
    // @grant none
    // ==/UserScript==
    // Function definitions
    function createAndAppendButton() {
    var input=document.createElement("input");
    input.type="button";
    input.value="Generate CSV Link";
    input.className="efinance-button";
    input.onclick = provideCSVLink;
    $("p.buttons").append(input);
    }

    function provideCSVLink() {
    var input=document.createElement("a");
    var csv = createCSV();
    var date = new Date();
    var year = date.getFullYear();
    var month = date.getMonth() + 1;
    var day = date.getDate();
    var filename = "ynab-" + year + "-" + month + "-" + day + ".csv";

    input.setAttribute('href','data:text/csv;charset=UTF-8,' + encodeURIComponent(csv));
    input.innerHTML = "Export to CSV";
    input.className="efinance-button";
    input.setAttribute('download',filename);

    $("p.buttons").append(input);
    }

    function createCSV() {
    var result = [];
    var lines = $("tbody").children("#detail_page tr");

    // push the header
    result.push('Date,Payee,Category,Memo,Outflow,Inflow');

    lines.each(function(){appendCreditDebitLine($(this),result)});

    return result.join("\n");
    }

    // Date,Payee,Category,Memo,Outflow,Inflow
    function appendCreditDebitLine(context, lines) {
    var line = [];
    var cells = context.children("td");
    var date = sanitize(cells.get(5));
    var payee = "";
    var category = "";
    var memo = sanitize(cells.get(2));
    var outflow = sanitize(cells.get(4));
    var inflow = sanitize(cells.get(3));


    // create a CSV line
    line.push(date);
    line.push(payee);
    line.push(category);
    line.push(memo);
    line.push(outflow);
    line.push(inflow);

    // append the CSV line
    lines.push(line.join(","));
    }

    function sanitize(cell) {
    return cell.innerHTML.replace(/<br>/gi," ").replace(/&nbsp;/gi,"").replace(/'/gi,'').trimLeft().trimRight()
    }

    /* waitForKeyElements(): A handy, utility function that
    * does what it says.
    */
    function waitForKeyElements (
    selectorTxt, /* Required: The jQuery selector string that
    specifies the desired element(s).
    */
    actionFunction, /* Required: The code to run when elements are
    found. It is passed a jNode to the matched
    element.
    */
    bWaitOnce, /* Optional: If false, will continue to scan for
    new elements even after the first match is
    found.
    */
    iframeSelector /* Optional: If set, identifies the iframe to
    search.
    */
    )
    {
    var targetNodes, btargetsFound;

    if (typeof iframeSelector == "undefined")
    targetNodes = $(selectorTxt);
    else
    targetNodes = $(iframeSelector).contents ()
    .find (selectorTxt);

    if (targetNodes && targetNodes.length > 0) {
    /*--- Found target node(s). Go through each and act if they
    are new.
    */
    targetNodes.each ( function () {
    var jThis = $(this);
    var alreadyFound = jThis.data ('alreadyFound') || false;

    if (!alreadyFound) {
    //--- Call the payload function.
    actionFunction (jThis);
    jThis.data ('alreadyFound', true);
    }
    } );
    btargetsFound = true;
    }
    else {
    btargetsFound = false;
    }

    //--- Get the timer-control variable for this selector.
    var controlObj = waitForKeyElements.controlObj || {};
    var controlKey = selectorTxt.replace (/[^\w]/g, "_");
    var timeControl = controlObj [controlKey];

    //--- Now set or clear the timer as appropriate.
    if (btargetsFound && bWaitOnce && timeControl) {
    //--- The only condition where we need to clear the timer.
    clearInterval (timeControl);
    delete controlObj [controlKey]
    }
    else {
    //--- Set a timer, if needed.
    if ( ! timeControl) {
    timeControl = setInterval ( function () {
    waitForKeyElements ( selectorTxt,
    actionFunction,
    bWaitOnce,
    iframeSelector
    );
    },
    500
    );
    controlObj [controlKey] = timeControl;
    }
    }
    waitForKeyElements.controlObj = controlObj;
    }

    // Main entry point
    waitForKeyElements ("p.buttons", createAndAppendButton);