Form Decoration Examples
Since you can add JavaScript to the Decoration-HTML, various ideas that enhance business efficiency can be realized. Accelerate your Workflow!!

Code Examples using JavaScript Selectors API or jQuery for UI developers.
The Decoration feature is available with Professional or Enterprise edition.
NOTE: No updates or support. Decoration is at your own risk.


Overwrite Title

Target: TITLE form (update)

<input type="text" name="title" value="Default String" id="title" class="fit">

Example of DESCRIPTION setting

vanilla JavaScript
Click to overwrite: 
<button type='button' id='btnTitleEn'>Export Procedure</button>
<button type='button' id='btnTitleJa'>輸出手続</button>
<script>
document.querySelector('#btnTitleEn').addEventListener('click', function() {
  document.querySelector("#title").value = 'Export Application';
});
document.querySelector('#btnTitleJa').addEventListener('click', function() {
  document.querySelector("#title").value = '輸出申請';
});
</script>
using jQuery (click to open)
Click to overwrite: 
<button type='button' id='btnTitleEn'>Export Procedure</button>
<button type='button' id='btnTitleJa'>輸出手続</button>
<script>
jQuery( "#btnTitleEn" ).on( "click", function(){ 
  jQuery( "#title" ).val( 'Export Application' );
});
jQuery( "#btnTitleJa" ).on( "click", function(){ 
  jQuery( "#title" ).val( '輸出申請' );
});
</script>

Capture


Append to String

Target: Singleline STRING form (append)

<input type="text" name="data[0].input" class="fit" value="" placeholder="">

Example of DESCRIPTION setting

vanilla JavaScript
Click to add Keywords: 
<button type='button' class='btnAddStr0'>javascript,</button>
<button type='button' class='btnAddStr0'>json,</button>
<button type='button' class='btnAddStr0'>workflow,</button>
<button type='button' class='btnAddStr0'>automation,</button>
<button type='button' class='btnAddStr0'>ワークフロー図,</button>
<button type='button' class='btnAddStr0'>書き方,</button>
<script>
document.querySelectorAll('.btnAddStr0').forEach( btn => {
  btn.addEventListener('click', () => {
    const strClicked0  = btn.textContent;
    const strOriginal0 = document.querySelector( 'input[name="data\\[0\\].input"]' ).value;
    document.querySelector( 'input[name="data\\[0\\].input"]' )
                .value = ( strOriginal0 + strClicked0 );
  });
});
</script>
using jQuery (click to open)
Click to add Keywords: 
<button type='button' class='btnAddStr0'>javascript,</button>
<button type='button' class='btnAddStr0'>json,</button>
<button type='button' class='btnAddStr0'>workflow,</button>
<button type='button' class='btnAddStr0'>automation,</button>
<button type='button' class='btnAddStr0'>ワークフロー図,</button>
<button type='button' class='btnAddStr0'>書き方,</button>
<script>
jQuery( ".btnAddStr0" ).on( "click", function(){ 
  const strClicked0  = jQuery( this ).text();
  const strOriginal0 = jQuery( 'input[name="data\\[0\\].input"]' ).val();
  jQuery( 'input[name="data\\[0\\].input"]' ).val( strOriginal0 + strClicked0 );
});
</script>

Capture


Validate String

Referrer: Multiline STRING form

<textarea name="data[1].input" placeholder="" class="fit"></textarea>

Target: div

<div id="divResult1"><span style="color:#0000aa;padding:20px;">(waiting)</span></div>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
Tsv Validation:<br />
<div id="divResult1"><span style="color:#0000aa;padding:20px;">(waiting)</span></div>
<script>
document.querySelector('textarea[name="data\\[1\\].input"]').addEventListener('change', function() {
  const strTsv1  = document.querySelector('textarea[name="data\\[1\\].input"]').value;
  let strResult1 = "";

  let arrCells1  = [];
  const arrTsv1  = strTsv1.split("\n");
  for( let i = 0; i < arrTsv1.length; i++ ){
    arrCells1[i] = [];
    let arrTmp = arrTsv1[i].split("\t");
    for( let j = 0; j < arrTmp.length; j++ ){
      arrCells1[i].push( arrTmp[j] );
    }
  }

  strResult1 += '<span style="color:#0000ff;">';
  strResult1 += "Number of RowLines: " + arrTsv1.length + "<br />";
  strResult1 += "Number of Columns0: " + arrCells1[0].length + "<br />";
  strResult1 += '</span>';
  strResult1 += "== Y:Exist, n:Empty ==<br />";
  for( let i = 0; i < arrCells1.length; i++ ){
    strResult1 += " [" + i + "]: ";
    for( let j = 0; j < arrCells1[i].length; j++ ){
      if( arrCells1[i][j] !== "" ){
        strResult1 += " Y";
      }else{
        strResult1 += " n";
      }
    }
    if( arrCells1[i].length !== arrCells1[0].length ){
      strResult1 += ' <span style="color:#ff0000;">' +
                    '(Mismatch with length of Line[0])' +
                    '</span>';
    }
    strResult1 += "<br />\n";
  }
  document.querySelector('#divResult1').innerHTML = strResult1;
});
</script>
using jQuery (click to open)
Tsv Validation:<br />
<div id="divResult1"><span style="color:#0000aa;padding:20px;">(waiting)</span></div>
<script>
jQuery( 'textarea[name="data\\[1\\].input"]' ).on( "change keyup", function(){
  const strTsv1  = jQuery( this ).val();
  let strResult1 = "";

  let arrCells1  = [];
  const arrTsv1  = strTsv1.split("\n");
  for( let i = 0; i < arrTsv1.length; i++ ){
    arrCells1[i] = [];
    let arrTmp = arrTsv1[i].split("\t");
    for( let j = 0; j < arrTmp.length; j++ ){
      arrCells1[i].push( arrTmp[j] );
    }
  }

  strResult1 += '<span style="color:#0000ff;">';
  strResult1 += "Number of RowLines: " + arrTsv1.length + "<br />";
  strResult1 += "Number of Columns0: " + arrCells1[0].length + "<br />";
  strResult1 += '</span>';
  strResult1 += "== Y:Exist, n:Empty ==<br />";
  for( let i = 0; i < arrCells1.length; i++ ){
    strResult1 += " [" + i + "]: ";
    for( let j = 0; j < arrCells1[i].length; j++ ){
      if( arrCells1[i][j] !== "" ){
        strResult1 += " Y";
      }else{
        strResult1 += " n";
      }
    }
    if( arrCells1[i].length !== arrCells1[0].length ){
      strResult1 += ' <span style="color:#ff0000;">' +
                    '(Mismatch with length of Line[0])' +
                    '</span>';
    }
    strResult1 += "<br />\n";
  }
  jQuery( "#divResult1" ).html( strResult1 );
});
</script>

Capture


Add Number

Target: NUMERIC form (update)

<input type="text" name="data[2].input" size="20" value="">

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
Click to add Number: 
<button type='button' class='btnAddNum2'>+100</button>
<button type='button' class='btnAddNum2'>+10</button>
<button type='button' class='btnAddNum2'>+1</button>
<button type='button' class='btnAddNum2'>-1</button>
<button type='button' class='btnAddNum2'>-10</button>
<button type='button' class='btnAddNum2'>-100</button>
<script>
document.querySelectorAll('.btnAddNum2').forEach( btn => {
  btn.addEventListener('click', () => {

    const strClicked2  = btn.textContent;
    const numClicked2  = parseFloat( strClicked2 );
    const strOriginal2 = document.querySelector( 'input[name="data\\[2\\].input"]' ).value;

    let   numOriginal2 = parseFloat( strOriginal2 );
    if( isNaN( numOriginal2 ) ){
          numOriginal2 = 0;
    }
    let   calcResult2  = numOriginal2 + numClicked2;
    document.querySelector( 'input[name="data\\[2\\].input"]' )
                .value = ( calcResult2 + "" );
  });
});
</script>
using jQuery (click to open)
Click to add Number: 
<button type='button' class='btnAddNum2'>+100</button>
<button type='button' class='btnAddNum2'>+10</button>
<button type='button' class='btnAddNum2'>+1</button>
<button type='button' class='btnAddNum2'>-1</button>
<button type='button' class='btnAddNum2'>-10</button>
<button type='button' class='btnAddNum2'>-100</button>
<script>
jQuery( ".btnAddNum2" ).on( "click", function(){ 
  const strClicked2  = jQuery( this ).text();
  const numClicked2  = parseFloat( strClicked2 );
  let   strOriginal2 = jQuery( 'input[name="data\\[2\\].input"]' ).val();
  let   numOriginal2 = parseFloat( strOriginal2 );
  if( isNaN( numOriginal2 ) ){
        numOriginal2 = 0;
  }
  let   calcResult2  = numOriginal2 + numClicked2;
  jQuery( 'input[name="data\\[2\\].input"]' ).val( calcResult2 );
});
</script>

Capture



Show Selected Value

Referrer: Radio SELECT form

<input type="radio" id="field-1_3-0" name="data[3].selects" value="false">
<label for="field-1_3-0" id="ext-gen1211">NO</label>
<input type="radio" id="field-1_3-1" name="data[3].selects" value="true">
<label for="field-1_3-1" id="ext-gen1212">YES</label>

Target: span

<span id="spanValue3" style="color:#0000aa;">(waiting)</span>
<span id="spanDisplay3" style="color:#0000aa;">(waiting)</span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
Selected Value: <span id="spanValue3" style="color:#0000aa;">(waiting)</span><br />
Selected Display: <span id="spanDisplay3" style="color:#0000aa;">(waiting)</span>
<script>
document.querySelectorAll('input[name="data\\[3\\].selects"]').forEach( inp => {
  inp.addEventListener('change', () => {
    const strValue3   = document.querySelector('input[name="data\\[3\\].selects"]:checked').value;
    const strId3      = document.querySelector('input[name="data\\[3\\].selects"]:checked').id;
    const strDisplay3 = document.querySelector('label[for="' + strId3 + '"]').textContent;
    document.querySelector( '#spanValue3' ).innerHTML = strValue3;
    document.querySelector( '#spanDisplay3' ).innerHTML = strDisplay3;
  });
});
</script>
using jQuery (click to open)
Selected Value: <span id="spanValue3" style="color:#0000aa;">(waiting)</span><br />
Selected Display: <span id="spanDisplay3" style="color:#0000aa;">(waiting)</span>
<script>
jQuery( "input[name='data\\[3\\].selects']" ).on( "change", function(){ 
  const strValue3   = jQuery( 'input[name="data\\[3\\].selects"]:checked' ).val();
  const strId3      = jQuery( 'input[name="data\\[3\\].selects"]:checked' ).attr('id');
  const strDisplay3 = jQuery( 'label[for="' + strId3 + '"]' ).text();
  jQuery( '#spanValue3' ).html( strValue3 );
  jQuery( '#spanDisplay3' ).html( strDisplay3 );
});
</script>

Capture


Uncheck Radio

Target: Target: Radio SELECT form

<input type="radio" id="field-1_3-0" name="data[3].selects" value="false">
<label for="field-1_3-0" id="ext-gen1211">NO</label>
<input type="radio" id="field-1_3-1" name="data[3].selects" value="true">
<label for="field-1_3-1" id="ext-gen1212">YES</label>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type='button' id='btnUncheck3'>Clear</button>
<script>
document.querySelector('#btnUncheck3').addEventListener('click', function(){
  if( document.querySelector('input[name="data\\[3\\].selects"]:checked') != null ){
    document.querySelector('input[name="data\\[3\\].selects"]:checked').checked = false;
  }
});
</script>

Capture

Workflow Decoration: Uncheck Radio

Copy to Clipboard

Referrer: Dropdown SELECT form

<select id="w0-field-1_4" name="data[4].selects" class="fit" onchange="Mediator.valueChanged(4);">
  <option value=""> </option>
  <option value="0001">みずほ銀行 MHCBJPJT</option>
  <option value="0005">三菱UFJ銀行 BOTKJPJT</option>
  <option value="0009">三井住友銀行 SMBCJPJT</option>
  <option value="0010">りそな銀行 DIWAJPJT</option>
  <option value="0017">埼玉りそな銀行 SAIBJPJT</option>
</select>

Target: span

<span id="spanOutput4" style="color:#0000aa;"></span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type='button' id='btnCopyValue4'>Copy VALUE</button>
<button type='button' id='btnCopyDisplay4'>Copy DISPLAY</button>
<span id="spanOutput4" style="color:#0000aa;"></span>
<script>
document.querySelector('#btnCopyValue4').addEventListener('click', function(){
  let elSelect = document.querySelector('select[name="data\\[4\\].selects"]');
  let numIdx   = elSelect.selectedIndex;
  // https://developer.mozilla.org/en-US/docs/Web/API/HTMLSelectElement
  let strSelectedValue   = "";
  if( numIdx >= 0 ){ // No element is selected: -1. Questetra's empty value: 0.
    strSelectedValue   = elSelect.options[numIdx].value;
    // https://developer.mozilla.org/en-US/docs/Web/API/HTMLOptionElement
    navigator.clipboard.writeText( strSelectedValue ).then(function() {
      document.querySelector('#spanOutput4').innerHTML = "Copied: '" + strSelectedValue + "'";
    }, function() {
      document.querySelector('#spanOutput4').innerHTML = "Unable to write to clipboard.";
    });
    // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
    // Internet Explorer not supported
  }
});
document.querySelector('#btnCopyDisplay4').addEventListener('click', function(){
  let elSelect = document.querySelector('select[name="data\\[4\\].selects"]');
  let numIdx   = elSelect.selectedIndex;
  let strSelectedDisplay = "";
  if( numIdx >= 0 ){
    strSelectedDisplay = elSelect.options[numIdx].text;
    navigator.clipboard.writeText( strSelectedDisplay ).then(function() {
      document.querySelector('#spanOutput4').innerHTML = "Copied: '" + strSelectedDisplay + "'";
    }, function() {
      document.querySelector('#spanOutput4').innerHTML = "Unable to write to clipboard.";
    });
  }
});
</script>

Capture

Workflow Decoration Copy to Clipboard

Show Selected Value 2

Referrer: Search SELECT form

<div class="x-hide-display x-form-data-hidden" role="presentation" id="ext-gen1225"><input type="hidden" name="data[5].selects" value=""></div>
<input id="ext-comp-1095-inputEl" type="text" role="combobox" class="x-form-field x-form-text x-form-focus x-field-form-focus
 x-field-default-form-focus" autocomplete="off" name="data[5].dummy" placeholder="Search for an item" data-errorqtip="" style="width: 100%;">
CAN:Ottawa:UTC-5(UTC-4),Canada
FRA:Paris:UTC+1(UTC+2):French Republic,France
DEU:Berlin:UTC+1(UTC+2):Federal Republic of Germany,Germany
ITA:Rome:UTC+1:Italian Republic,Italy
JPN:Tokyo:UTC+9:Japan,Japan
GBR:London:UTC(UTC+1):United Kingdom of Great Britain and Northern Ireland,United Kingdom
USA:Washington D.C.:UTC-5(UTC-4):United States of America,United States

Target: span

<span style="color:#0000aa;" id="spanResult5"> (waiting)</span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type='button' id='btnNote5'>Show Note</button><br />
Note:<br />
<span style="color:#0000aa;" id="spanResult5"> (waiting)</span>
<script>
document.querySelector('#btnNote5').addEventListener('click', function() {
  const strValue5   = document.querySelector('input[name="data\\[5\\].selects"]').value;
  const strDisplay5 = document.querySelector('input[name="data\\[5\\].dummy"]').value;
  // note: input do not exist on loaded
  // note: hidden input fields do not trigger the change event
  document.querySelector('#spanResult5').innerHTML = " " + strDisplay5 + "<br /> " + strValue5;
});
</script>

Capture

Workflow Decoration: Search Select Value as Note

Check All

Target: Checkbox SELECT form

<div class="section group">
<div class="col span_1_of_4" data-cell-index="0"><div class="option" data-item-index="0">
<input type="checkbox" id="field-1_6-0" name="data[6].selects" value="CAN">
<label for="field-1_6-0">Canada</label></div></div>
<div class="col span_1_of_4" data-cell-index="1"><div class="option" data-item-index="1">
<input type="checkbox" id="field-1_6-1" name="data[6].selects" value="FRA">
<label for="field-1_6-1">France</label></div></div>
<div class="col span_1_of_4" data-cell-index="2"><div class="option" data-item-index="2">
<input type="checkbox" id="field-1_6-2" name="data[6].selects" value="DEU">
<label for="field-1_6-2">Germany</label></div></div>
<div class="col span_1_of_4" data-cell-index="3"><div class="option" data-item-index="3">
<input type="checkbox" id="field-1_6-3" name="data[6].selects" value="ITA">
<label for="field-1_6-3">Italy</label></div></div>
</div>
<div class="section group">
<div class="col span_1_of_4" data-cell-index="4"><div class="option" data-item-index="4">
<input type="checkbox" id="field-1_6-4" name="data[6].selects" value="JPN">
<label for="field-1_6-4">Japan</label></div></div>
<div class="col span_1_of_4" data-cell-index="5"><div class="option" data-item-index="5">
<input type="checkbox" id="field-1_6-5" name="data[6].selects" value="GBR">
<label for="field-1_6-5">United Kingdom</label></div></div>
<div class="col span_1_of_4" data-cell-index="6"><div class="option" data-item-index="6">
<input type="checkbox" id="field-1_6-6" name="data[6].selects" value="USA">
<label for="field-1_6-6">United States</label></div></div>
<div class="col span_1_of_4" data-cell-index="7"></div>
</div>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<div style="text-align:right">
<button type="button" onclick="checkAll6()" style="margin: 0px 10px;">Check All</button>
<button type="button" onclick="uncheckAll6()" style="margin: 0px 10px;">Uncheck All</button>
</div>
<script>
function checkAll6(){
  const elCheckboxes6 = document.querySelectorAll('input[name="data\\[6\\].selects"]');
  for(let i = 0; i < elCheckboxes6.length; i++) {
    elCheckboxes6[i].checked = true;
  }
}
function uncheckAll6(){
  const elCheckboxes6 = document.querySelectorAll('input[name="data\\[6\\].selects"]');
  for(let i = 0; i < elCheckboxes6.length; i++) {
    elCheckboxes6[i].checked = false;
  }
}
</script>

Capture


Count Days

Referrer: YYYY-MM-DD DATE form

<input id="ext-gen1031-inputEl" type="text" role="textbox" size="1" name="data[7].input" placeholder="YYYY-MM-DD"
 class="x-form-field x-form-text x-form-focus x-field-form-focus x-field-default-form-focus" autocomplete="off" data-errorqtip="" style="width: 100%;">

Target: span

<span style="color:#0000aa;" id="spanResult7"> (waiting)</span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<div style="text-align:right">
<span style="color:#0000aa;" id="spanResult7"> (waiting)</span>
<button type="button" onclick="countDays7()" style="margin: 0px 10px;"> << Count Days</button>
</div>
<script>
function countDays7(e) {
  if( document.querySelector('input[name="data\\[7\\].input"]').value === "" ) return;
  const strDatetime7 =
          document.querySelector('input[name="data\\[7\\].input"]').value + " 23:59";
  const date7   = toJsDate( strDatetime7 );
  const dateNow = new Date();
  let numDuration = date7.getTime() - dateNow.getTime();
  let numDays     = numDuration /1000 /60 /60 /24;
  let numHours    = numDuration /1000 /60 /60;
  let strStyle    = "";
  let strMessage  = "";
  if( numDays > 365 ){
    strMessage  = Math.floor( numDays ) + " days from now";
    strStyle    = "10px dotted #A55B9A";
  }else if( numDays > 30 ){
    strMessage  = Math.floor( numDays ) + " days from now";
    strStyle    = "7px dotted #5D5099";
  }else if( numDays > 7 ){
    strMessage  = Math.floor( numDays ) + " days from now";
    strStyle    = "4px dotted #4784BF";
  }else if( numDays > 1 ){
    strMessage  = Math.floor( numDays ) + " days from now";
    strStyle    = "2px dotted #00AEE0";
  }else if( numDays > 0 ){
    strMessage  = "<strong>" + Math.floor( numHours ) + " hours</strong> from now";
    strStyle    = "2px dotted #00AEE0";
  }else if( -365 > numDays ){
    strMessage  = Math.floor( -numDays ) + " days ago";
    strStyle    = "10px double #DE6641";
  }else if( -30 > numDays ){
    strMessage  = Math.floor( -numDays ) + " days ago";
    strStyle    = "7px double #E8AC51";
  }else if( -7 > numDays ){
    strMessage  = Math.floor( -numDays ) + " days ago";
    strStyle    = "4px double #F2E55C";
  }else if( -1 > numDays ){
    strMessage  = Math.floor( -numDays ) + " days ago";
    strStyle    = "2px double #F2E55C";
  }else{
    strMessage  = "<strong>" + Math.floor( -numHours ) + " hours</strong> ago";
    strStyle    = "2px double #F2E55C";
  }
  document.querySelector('#spanResult7').style.borderBottom = strStyle;
  document.querySelector('#spanResult7').innerHTML = strMessage;
}
function toJsDate( bpmsDateOrDatetimeStr ){
  // BPMS Date:     "2020-04-01"  (subtype "Y/M" "M/D" "Y", not supported)
  // BPMS Datetime: "2020-04-01 23:59"
  let year       = 0;
  let monthIndex = 0;
  let day        = 0;
  let hours      = 0;
  let minutes    = 0;
  //  The ECMA/JavaScript Date object has a large number of methods.
  // "Date.parse" is danger (strongly discouraged)
  // - new Date("2014-11-10") // Mon Nov 10 2014 09:00:00 GMT+0900 (JST)
  // - new Date(2014, 10, 10) // Mon Nov 10 2014 00:00:00 GMT+0900 (JST)
  let arrDatetime = bpmsDateOrDatetimeStr.split(" ");
  if( arrDatetime.length === 1 ){
    let arrDateParts = arrDatetime[0].split("-");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
  }
  if( arrDatetime.length === 2 ){
    let arrDateParts = arrDatetime[0].split("-");
    let arrTimeParts = arrDatetime[1].split(":");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
    hours      = parseInt(arrTimeParts[0], 10);
    minutes    = parseInt(arrTimeParts[1], 10);
  }
  return new Date( year, monthIndex, day, hours, minutes );
}
</script>

Capture

Workflow Decoration: Count Days

Check Future

Referrer: DATETIME form

<input id="ext-gen1069-inputEl" type="text" role="textbox" size="1" name="data[11].input" placeholder="YYYY-MM-DD"
 class="x-form-field x-form-empty-field x-form-text" autocomplete="off" data-errorqtip="" style="width: 100%;">

<input id="ext-gen1070-inputEl" type="text" role="combobox" class="x-form-field x-form-text x-form-focus x-field-form-focus
 x-field-default-form-focus" autocomplete="off" name="data[11].time" placeholder="HH:MM" data-errorqtip="" style="width: 100%;">

Target: span

<span style="color:#0000aa;" id="spanResult11"> (waiting)</span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<div style="text-align:right">
<span style="color:#0000aa;" id="spanResult11"> (waiting)</span>
<button type="button" onclick="showDays11()" style="margin: 0px 10px;"> << Show Days</button>
</div>
<script>
function showDays11(e) {
  if( document.querySelector('input[name="data\\[11\\].input"]').value === "" ) return;
  if( document.querySelector('input[name="data\\[11\\].time"]').value === "" ) return;
  const strDatetime11 =
          document.querySelector('input[name="data\\[11\\].input"]').value + " " +
          document.querySelector('input[name="data\\[11\\].time"]').value;
  const date11  = toJsDate( strDatetime11 );
  const dateNow = new Date();
  let numDuration = date11.getTime() - dateNow.getTime();
  let numDays     = numDuration /1000 /60 /60 /24;
  let numHours    = numDuration /1000 /60 /60;
  let strStyle    = "";
  let strMessage  = "";
  if( numDays > 365 ){
    strMessage  = Math.floor( numDays ) + " days from now";
    strStyle    = "10px dotted #A55B9A";
  }else if( numDays > 30 ){
    strMessage  = Math.floor( numDays ) + " days from now";
    strStyle    = "7px dotted #5D5099";
  }else if( numDays > 7 ){
    strMessage  = Math.floor( numDays ) + " days from now";
    strStyle    = "4px dotted #4784BF";
  }else if( numDays > 1 ){
    strMessage  = Math.floor( numDays ) + " days from now";
    strStyle    = "2px dotted #00AEE0";
  }else if( numDays > 0 ){
    strMessage  = "<strong>" + Math.floor( numHours ) + " hours</strong> from now";
    strStyle    = "2px dotted #00AEE0";
  }else if( -365 > numDays ){
    strMessage  = Math.floor( -numDays ) + " days ago";
    strStyle    = "10px double #DE6641";
  }else if( -30 > numDays ){
    strMessage  = Math.floor( -numDays ) + " days ago";
    strStyle    = "7px double #E8AC51";
  }else if( -7 > numDays ){
    strMessage  = Math.floor( -numDays ) + " days ago";
    strStyle    = "4px double #F2E55C";
  }else if( -1 > numDays ){
    strMessage  = Math.floor( -numDays ) + " days ago";
    strStyle    = "2px double #F2E55C";
  }else{
    strMessage  = "<strong>" + Math.floor( -numHours ) + " hours</strong> ago";
    strStyle    = "2px double #F2E55C";
  }
  document.querySelector('#spanResult11').style.borderBottom = strStyle;
  document.querySelector('#spanResult11').innerHTML = strMessage;
}
function toJsDate( bpmsDateOrDatetimeStr ){
  // BPMS Date:     "2020-04-01"  (subtype "Y/M" "M/D" "Y", not supported)
  // BPMS Datetime: "2020-04-01 23:59"
  let year       = 0;
  let monthIndex = 0;
  let day        = 0;
  let hours      = 0;
  let minutes    = 0;
  //  The ECMA/JavaScript Date object has a large number of methods.
  // "Date.parse" is danger (strongly discouraged)
  // - new Date("2014-11-10") // Mon Nov 10 2014 09:00:00 GMT+0900 (JST)
  // - new Date(2014, 10, 10) // Mon Nov 10 2014 00:00:00 GMT+0900 (JST)
  let arrDatetime = bpmsDateOrDatetimeStr.split(" ");
  if( arrDatetime.length === 1 ){
    let arrDateParts = arrDatetime[0].split("-");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
  }
  if( arrDatetime.length === 2 ){
    let arrDateParts = arrDatetime[0].split("-");
    let arrTimeParts = arrDatetime[1].split(":");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
    hours      = parseInt(arrTimeParts[0], 10);
    minutes    = parseInt(arrTimeParts[1], 10);
  }
  return new Date( year, monthIndex, day, hours, minutes );
}
</script>

Capture

Workflow Decoration: Check Future at Datetime form

Add Date

Target: YYYY-MM-DD DATE form

<input id="ext-gen1031-inputEl" type="text" role="textbox" size="1" name="data[7].input" placeholder="YYYY-MM-DD"
 class="x-form-field x-form-text x-form-focus x-field-form-focus x-field-default-form-focus" autocomplete="off" data-errorqtip="" style="width: 100%;">

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
2020-01-01 +1m → 2020-02-01<br />
2020-01-31 +1m → 2020-03-02<br />
<button type='button' onclick='btnAddDate7(this)'>+1y</button>
<button type='button' onclick='btnAddDate7(this)'>+1m</button>
<button type='button' onclick='btnAddDate7(this)'>+7d</button>
<button type='button' onclick='btnAddDate7(this)'>+1d</button> - 
<button type='button' onclick='btnAddDate7(this)'>-1y</button>
<button type='button' onclick='btnAddDate7(this)'>-1m</button>
<button type='button' onclick='btnAddDate7(this)'>-7d</button>
<button type='button' onclick='btnAddDate7(this)'>-1d</button>
<script>
function btnAddDate7(elBtn) {
  let elTarget = document.querySelector('input[name="data\\[7\\].input"]');
  if( elTarget.value === "" ) return;
  const strOriginal = elTarget.value;
  const strClicked  = elBtn.textContent;
  const numClicked  = parseFloat( strClicked );
  const strLast     = strClicked.slice( -1 ); // y:year, m:month, d:day
  let dateNew = toJsDate( strOriginal );
  if( strLast == "y" ){
    dateNew.setFullYear( dateNew.getFullYear() + numClicked );
  }else if( strLast == "m" ){
    dateNew.setMonth( dateNew.getMonth() + numClicked );
  }else if( strLast == "d" ){
    dateNew.setDate( dateNew.getDate() + numClicked );
  }
  elTarget.value = dateNew.toISOString().slice(0,10);
}
function toJsDate( bpmsDateOrDatetimeStr ){
  // BPMS Date:     "2020-04-01"  (subtype "Y/M" "M/D" "Y", not supported)
  // BPMS Datetime: "2020-04-01 23:59"
  let year       = 0;
  let monthIndex = 0;
  let day        = 0;
  let hours      = 0;
  let minutes    = 0;
  //  The ECMA/JavaScript Date object has a large number of methods.
  // "Date.parse" is danger (strongly discouraged)
  // - new Date("2014-11-10") // Mon Nov 10 2014 09:00:00 GMT+0900 (JST)
  // - new Date(2014, 10, 10) // Mon Nov 10 2014 00:00:00 GMT+0900 (JST)
  let arrDatetime = bpmsDateOrDatetimeStr.split(" ");
  if( arrDatetime.length === 1 ){
    let arrDateParts = arrDatetime[0].split("-");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
  }
  if( arrDatetime.length === 2 ){
    let arrDateParts = arrDatetime[0].split("-");
    let arrTimeParts = arrDatetime[1].split(":");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
    hours      = parseInt(arrTimeParts[0], 10);
    minutes    = parseInt(arrTimeParts[1], 10);
  }
  return new Date( year, monthIndex, day, hours, minutes );
}
</script>

Capture

Workflow Decoration: Add Date

Set Time

Target: DATETIME form

<input id="ext-gen1069-inputEl" type="text" role="textbox" size="1" name="data[11].input" placeholder="YYYY-MM-DD"
 class="x-form-field x-form-empty-field x-form-text" autocomplete="off" data-errorqtip="" style="width: 100%;">

<input id="ext-gen1070-inputEl" type="text" role="combobox" class="x-form-field x-form-text x-form-focus x-field-form-focus
 x-field-default-form-focus" autocomplete="off" name="data[11].time" placeholder="HH:MM" data-errorqtip="" style="width: 100%;">

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type='button' onclick='btnSetTime11(this)'>09:00</button>
<button type='button' onclick='btnSetTime11(this)'>09:30</button>
<button type='button' onclick='btnSetTime11(this)'>10:00</button>
<button type='button' onclick='btnSetTime11(this)'>13:00</button><br />
<button type='button' onclick='btnAddTime11(this)'>+60</button>
<button type='button' onclick='btnAddTime11(this)'>+10</button>
<button type='button' onclick='btnAddTime11(this)'>+1</button>,
<button type='button' onclick='btnAddTime11(this)'>-1</button>
<button type='button' onclick='btnAddTime11(this)'>-10</button>
<button type='button' onclick='btnAddTime11(this)'>-60</button>
<script>
function btnSetTime11(elBtn) {
  const elTime   = document.querySelector('input[name="data\\[11\\].time"]');
  elTime.value = elBtn.textContent;
}
function btnAddTime11(elBtn) {
  const elDate = document.querySelector('input[name="data\\[11\\].input"]');
  const elTime = document.querySelector('input[name="data\\[11\\].time"]');
  if( elDate.value === "" ) return;
  if( elTime.value === "" ) return;
  const strOriginal = elDate.value + " " + elTime.value;
  const strClicked  = elBtn.textContent;
  const numClicked  = parseFloat( strClicked );
  let dateOriginal  = toJsDate( strOriginal );
  let dateUpdated   = new Date( dateOriginal.getTime() + (numClicked * 60000) );
  elDate.value = dateUpdated.toISOString().slice(0,10);
  elTime.value = dateUpdated.toISOString().slice(11,16);
}
function toJsDate( bpmsDateOrDatetimeStr ){
  // BPMS Date:     "2020-04-01"  (subtype "Y/M" "M/D" "Y", not supported)
  // BPMS Datetime: "2020-04-01 23:59"
  let year       = 0;
  let monthIndex = 0;
  let day        = 0;
  let hours      = 0;
  let minutes    = 0;
  //  The ECMA/JavaScript Date object has a large number of methods.
  // "Date.parse" is danger (strongly discouraged)
  // - new Date("2014-11-10") // Mon Nov 10 2014 09:00:00 GMT+0900 (JST)
  // - new Date(2014, 10, 10) // Mon Nov 10 2014 00:00:00 GMT+0900 (JST)
  let arrDatetime = bpmsDateOrDatetimeStr.split(" ");
  if( arrDatetime.length === 1 ){
    let arrDateParts = arrDatetime[0].split("-");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
  }
  if( arrDatetime.length === 2 ){
    let arrDateParts = arrDatetime[0].split("-");
    let arrTimeParts = arrDatetime[1].split(":");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
    hours      = parseInt(arrTimeParts[0], 10);
    minutes    = parseInt(arrTimeParts[1], 10);
  }
  return new Date( year, monthIndex, day, hours, minutes );
}
</script>

Capture

Workflow Decoration: Set Time

Quote Readonly

Referrer: STRING form (read only)

<div id="readonly_0" class="fit">
<div class="auto-link" id="ext-gen1031">I forgot my password.<br>
What should I do?<br>
</div>
</div>

Target: Multiline STRING form

<textarea name="data[1].input" rows="5" placeholder="" style="resize: both;" class="fit"></textarea>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type="button" onclick="quote0to1()"> Quote from String0 INQUERY </button>
<script>
function quote0to1() {
  const elReferrer = document.querySelector('#readonly_0');
  const elTarget   = document.querySelector('textarea[name="data\\[1\\].input"]');

  let strResult = "";
  let arrTmp = elReferrer.innerText.split("\n");
  for( let i = 0; i < arrTmp.length; i++ ){
    if( i !== (arrTmp.length - 1) || arrTmp[i] !== "" ){
      strResult += "> " + arrTmp[i] + "\n";
    }
  }
  elTarget.value = strResult;
}
</script>

Capture

Workflow Decoration: Quote Read Only

Local Date String

Referrer: YYYY-MM-DD DATE form

<input id="ext-gen1031-inputEl" type="text" role="textbox" size="1" name="data[7].input" placeholder="YYYY-MM-DD"
 class="x-form-field x-form-text x-form-focus x-field-form-focus x-field-default-form-focus" autocomplete="off" data-errorqtip="" style="width: 100%;">

Target: STRING form

<input type="text" name="data[19].input" class="fit" value="hello world" placeholder="">

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<div style="text-align:right">
<button type="button" onclick="convert7enUS19()" style="margin: 0px 10px;"> ↓ en-US </button>
<button type="button" onclick="convert7enUSLA19()" style="margin: 0px 10px;"> ↓ en-US2 </button>
<button type="button" onclick="convert7enGB19()" style="margin: 0px 10px;"> ↓ en-GB </button>
<button type="button" onclick="convert7enGBUTC19()" style="margin: 0px 10px;"> ↓ en-GB2 </button>
<button type="button" onclick="convert7jaJP19()" style="margin: 0px 10px;"> ↓ ja-JP </button>
<button type="button" onclick="convert7jaJPw19()" style="margin: 0px 10px;"> ↓ ja-JP2 </button>
</div>
<script>
function convert7enUS19() {
  const elReferrer   = document.querySelector('input[name="data\\[7\\].input"]');
  const elTarget     = document.querySelector('input[name="data\\[19\\].input"]');
  const strReferrer  = elReferrer.value;
  if( strReferrer === "" ) return;
  const dateReferrer = toJsDate( strReferrer );
  let options    = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long',
                     timeZoneName: 'short' };
  let strResult  = new Intl.DateTimeFormat( 'en-US', options ).format( dateReferrer );
  elTarget.value = strResult;
}
function convert7enUSLA19() {
  const elReferrer   = document.querySelector('input[name="data\\[7\\].input"]');
  const elTarget     = document.querySelector('input[name="data\\[19\\].input"]');
  const strReferrer  = elReferrer.value;
  if( strReferrer === "" ) return;
  const dateReferrer = toJsDate( strReferrer );
  let options    = { year: 'numeric', month: 'long', day: 'numeric', weekday: 'long',
                     timeZone: 'America/Los_Angeles', timeZoneName: 'long' };
  let strResult  = new Intl.DateTimeFormat( 'en-US', options ).format( dateReferrer );
  elTarget.value = strResult;
}
function convert7enGB19() {
  const elReferrer   = document.querySelector('input[name="data\\[7\\].input"]');
  const elTarget     = document.querySelector('input[name="data\\[19\\].input"]');
  const strReferrer  = elReferrer.value;
  if( strReferrer === "" ) return;
  const dateReferrer = toJsDate( strReferrer );
  let options    = { year: 'numeric', month: 'long', day: 'numeric', 
                     timeZoneName: 'short' };
  let strResult  = new Intl.DateTimeFormat( 'en-GB', options ).format( dateReferrer );
  elTarget.value = strResult;
}
function convert7enGBUTC19() {
  const elReferrer   = document.querySelector('input[name="data\\[7\\].input"]');
  const elTarget     = document.querySelector('input[name="data\\[19\\].input"]');
  const strReferrer  = elReferrer.value;
  if( strReferrer === "" ) return;
  const dateReferrer = toJsDate( strReferrer );
  let options    = { year: 'numeric', month: 'long', day: 'numeric', 
                     timeZone: 'UTC', timeZoneName: 'long' };
  let strResult  = new Intl.DateTimeFormat( 'en-GB', options ).format( dateReferrer );
  elTarget.value = strResult;
}
function convert7jaJP19() {
  const elReferrer   = document.querySelector('input[name="data\\[7\\].input"]');
  const elTarget     = document.querySelector('input[name="data\\[19\\].input"]');
  const strReferrer  = elReferrer.value;
  if( strReferrer === "" ) return;
  const dateReferrer = toJsDate( strReferrer );
  let options    = { era: 'long', year: 'numeric', month: 'long', day: 'numeric' };
  let strResult  = new Intl.DateTimeFormat( 'ja-JP-u-ca-japanese', options ).format( dateReferrer );
  // BCP 47 extension tag. JavaScript internationalization functions use the "u" (Unicode) extension.
  // for use Japanese Era (和暦/皇歴). Unicode locale, key:ca (calendar), type:japanese
  // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Intl
  elTarget.value = strResult;
}
function convert7jaJPw19() {
  const elReferrer   = document.querySelector('input[name="data\\[7\\].input"]');
  const elTarget     = document.querySelector('input[name="data\\[19\\].input"]');
  const strReferrer  = elReferrer.value;
  if( strReferrer === "" ) return;
  const dateReferrer = toJsDate( strReferrer );
  let options    = { era: 'long', year: 'numeric', month: 'long', day: 'numeric', weekday: 'short' };
  let strResult  = new Intl.DateTimeFormat( 'ja-JP-u-ca-japanese', options ).format( dateReferrer );
  elTarget.value = strResult;
}
function toJsDate( bpmsDateOrDatetimeStr ){
  // BPMS Date:     "2020-04-01"  (subtype "Y/M" "M/D" "Y", not supported)
  // BPMS Datetime: "2020-04-01 23:59"
  let year       = 0;
  let monthIndex = 0;
  let day        = 0;
  let hours      = 0;
  let minutes    = 0;
  //  The ECMA/JavaScript Date object has a large number of methods.
  // "Date.parse" is danger (strongly discouraged)
  // - new Date("2014-11-10") // Mon Nov 10 2014 09:00:00 GMT+0900 (JST)
  // - new Date(2014, 10, 10) // Mon Nov 10 2014 00:00:00 GMT+0900 (JST)
  let arrDatetime = bpmsDateOrDatetimeStr.split(" ");
  if( arrDatetime.length === 1 ){
    let arrDateParts = arrDatetime[0].split("-");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
  }
  if( arrDatetime.length === 2 ){
    let arrDateParts = arrDatetime[0].split("-");
    let arrTimeParts = arrDatetime[1].split(":");
    year       = parseInt(arrDateParts[0], 10);
    monthIndex = parseInt(arrDateParts[1], 10) - 1;
    day        = parseInt(arrDateParts[2], 10);
    hours      = parseInt(arrTimeParts[0], 10);
    minutes    = parseInt(arrTimeParts[1], 10);
  }
  return new Date( year, monthIndex, day, hours, minutes );
}
</script>

Capture

Workflow Decoration: Convert Date to LocalDateString

Tokenize

Target: STRING form

<input type="text" name="data[21].input" class="fit" value="" placeholder="">

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<style>
button#stripeTokenization {
  background: #666EE8;
  color: white;
  border-radius: 4px;
  font-size: 13px;
  margin: 6px;
}
button#stripeTokenization:focus {
  background: #555ABF;
}
button#stripeTokenization:active {
  background: #43458B;
}
.StripeElement {
  box-sizing: border-box;
  height: 40px;
  padding: 10px 12px;
  border: 1px solid transparent;
  border-radius: 4px;
  background-color: white;
  box-shadow: 0 1px 3px 0 #e6ebf1;
  -webkit-transition: box-shadow 150ms ease;
  transition: box-shadow 150ms ease;
}
.StripeElement--focus {
  box-shadow: 0 1px 3px 0 #cfd7df;
}
.StripeElement--invalid {
  border-color: #fa755a;
}
.StripeElement--webkit-autofill {
  background-color: #fefde5 !important;
}
</style>
<div style="width: 95%; margin: 2px auto;">
  <button type="button" id="stripeTokenization">↑ Tokenization</button>
  <span style="font-size:10px">by <strong>
    <a href="https://stripe.com/" target="_Blank">Stripe.com</a></strong></span><br />
  <div id="card-element" class="field"></div><div id="card-errors"></div><div id="card-success"></div>
</div>
<script>
getScript('https://js.stripe.com/v3/', function () {
  const elTarget = document.querySelector('input[name="data\\[21\\].input"]');
  var stripe = Stripe('pk_test_XXXXXxxxxxYYYYYyyyyyZZZZ'); // Create a Stripe client

  var elements = stripe.elements(); // Create an instance of Elements
  var cardStyle = {
    base: {
      color: '#32325d', fontFamily: '"Helvetica Neue", Helvetica, sans-serif',
      fontSize: '13px', '::placeholder': { color: '#aab7c4' }
    },
    invalid: {
      color: '#fa755a', iconColor: '#fa755a'
    }
  };
  var card = elements.create('card', { hidePostalCode: true, style: cardStyle } );
  card.mount('#card-element');

  card.addEventListener('change', function(event) {  // real-time validation
    var displayError = document.getElementById('card-errors');
    if (event.error) { displayError.textContent = event.error.message;
    } else { displayError.textContent = ''; }
  });

  var tokenizeButton = document.getElementById('stripeTokenization');
  tokenizeButton.addEventListener('click', function(event) {
    var extraDetails = {};
    stripe.createToken(card, extraDetails).then(function(result) {
      if (result.error) {
        var errorElement = document.getElementById('card-errors');
        errorElement.textContent = result.error.message;
      } else {
        elTarget.value = result.token.id;
        // document.getElementById('card-success').textContent = "Token " + result.token.id;
        elTarget.readOnly = true;
        elTarget.style.backgroundColor = "#f2f2f2";
      }
    });
  });
});
function getScript(scriptUrl, callback) {
  const script = document.createElement('script');
  script.src = scriptUrl;
  script.onload = callback;
  document.body.appendChild(script);
}
</script>

Capture

Workflow Decoration: Tokenize

CSS Control

Target: Guide Panel

<div class="column column-1 " data-pdd-number="17"><div class="help tform-html-panel-body"></div></div>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<p style="text-align:center;color:#ff0000;margin-top:16px">Note:
 Using a Developer Account is subject to our Terms of Service</p>
<script>
(function () { // "window.onload=function(){" - "};" is better if there is Date "x-panel".
  if( document.getElementById("pi-search-form-pre") !== null ){
    console.log( "CSS Control does not work in Human tasks" );
    return;
  } // CSS not controlled, in performing My Tasks.

  // Margin Area
  document.querySelectorAll( '.all-wrapper, .page-body, .iframe-content' ).forEach( el => {
    el.style.padding = "0px 0px 0px 0px";
  });
  document.querySelector( '#taskForm' ).style.margin = "0px";
  document.querySelector( 'h3.system' ).style.border = "0px";

  // FormInput Area
  document.querySelectorAll( '.normal-tform, .x-panel-body-default' ).forEach( el => {
    el.style.backgroundColor = "#ffffff";
    el.style.borderColor = "#ffffff";
  });

  // SubmitButton (FormAction) Area
  document.querySelectorAll( '.tform-action' ).forEach( el => {
    el.style.backgroundColor = "#ffffff";
    el.style.borderColor = "#ffffff";
  });

  // Misc
  document.querySelector( '#submitButton' ).value = "Start 60-day free trial";
  document.querySelector( 'div.footer' ).remove();
}());
</script>

Capture

Workflow Decoration: CSS Control
%d bloggers like this: