Form Decoration Examples

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 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='user_btnTitleEn'>Export Procedure</button>
<button type='button' id='user_btnTitleJa'>輸出手続</button>
<script>
document.querySelector('#user_btnTitleEn').addEventListener('click', function() {
  document.querySelector("#title").value = 'Export Application';
});
document.querySelector('#user_btnTitleJa').addEventListener('click', function() {
  document.querySelector("#title").value = '輸出申請';
});
</script>
using jQuery (click to open)
Click to overwrite: 
<button type='button' id='user_btnTitleEn'>Export Procedure</button>
<button type='button' id='user_btnTitleJa'>輸出手続</button>
<script>
jQuery( "#user_btnTitleEn" ).on( "click", function(){ 
  jQuery( "#title" ).val( 'Export Application' );
});
jQuery( "#user_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='user_btnAddStr0'>javascript,</button>
<button type='button' class='user_btnAddStr0'>json,</button>
<button type='button' class='user_btnAddStr0'>workflow,</button>
<button type='button' class='user_btnAddStr0'>automation,</button>
<button type='button' class='user_btnAddStr0'>ワークフロー図,</button>
<button type='button' class='user_btnAddStr0'>書き方,</button>
<script>
document.querySelectorAll('.user_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='user_btnAddStr0'>javascript,</button>
<button type='button' class='user_btnAddStr0'>json,</button>
<button type='button' class='user_btnAddStr0'>workflow,</button>
<button type='button' class='user_btnAddStr0'>automation,</button>
<button type='button' class='user_btnAddStr0'>ワークフロー図,</button>
<button type='button' class='user_btnAddStr0'>書き方,</button>
<script>
jQuery( ".user_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


Count Characters

Referrer: Multiline STRING form

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

Target: span

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

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type='button' onclick='user_countString0()'>Count Characters (WhiteSpaces Removed)</button>
<span id="user_spanOutput0" style="color:#0000aa;">0 chs (0 chs)</span>
<script>
function user_countString0(){
  const strString0 = document.querySelector( 'textarea[name="data\\[0\\].input"]' ).value;
  const strVisible = strString0.trim().replace(/\s+/g, ' '); // also `\t` to space
  // White Spaces: spaces, tabs or line breaks
  // https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Whitespace
  // https://developer.mozilla.org/ja/docs/Web/API/Document_Object_Model/Whitespace

  document.querySelector('#user_spanOutput0').innerHTML =  [...strString0].length + " chs (" + [...strVisible].length + " chs)";
  // Spread Syntax
  // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax
  // https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax
}
</script>

Capture


Validate String

Referrer: Multiline STRING form

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

Target: div

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

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
Tsv Validation:<br />
<div id="user_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('#user_divResult1').innerHTML = strResult1;
});
</script>
using jQuery (click to open)
Tsv Validation:<br />
<div id="user_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( "#user_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='user_btnAddNum2'>+100</button>
<button type='button' class='user_btnAddNum2'>+10</button>
<button type='button' class='user_btnAddNum2'>+1</button>
<button type='button' class='user_btnAddNum2'>-1</button>
<button type='button' class='user_btnAddNum2'>-10</button>
<button type='button' class='user_btnAddNum2'>-100</button>
<script>
document.querySelectorAll('.user_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='user_btnAddNum2'>+100</button>
<button type='button' class='user_btnAddNum2'>+10</button>
<button type='button' class='user_btnAddNum2'>+1</button>
<button type='button' class='user_btnAddNum2'>-1</button>
<button type='button' class='user_btnAddNum2'>-10</button>
<button type='button' class='user_btnAddNum2'>-100</button>
<script>
jQuery( ".user_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="user_spanValue3" style="color:#0000aa;">(waiting)</span>
<span id="user_spanDisplay3" style="color:#0000aa;">(waiting)</span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
Selected Value: <span id="user_spanValue3" style="color:#0000aa;">(waiting)</span><br />
Selected Display: <span id="user_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( '#user_spanValue3' ).innerHTML = strValue3;
    document.querySelector( '#user_spanDisplay3' ).innerHTML = strDisplay3;
  });
});
</script>
using jQuery (click to open)
Selected Value: <span id="user_spanValue3" style="color:#0000aa;">(waiting)</span><br />
Selected Display: <span id="user_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( '#user_spanValue3' ).html( strValue3 );
  jQuery( '#user_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='user_btnUncheck3'>Clear</button>
<script>
document.querySelector('#user_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="user_spanOutput4" style="color:#0000aa;"></span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type='button' id='user_btnCopyValue4'>Copy VALUE</button>
<button type='button' id='user_btnCopyDisplay4'>Copy DISPLAY</button>
<span id="user_spanOutput4" style="color:#0000aa;"></span>
<script>
document.querySelector('#user_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('#user_spanOutput4').innerHTML = "Copied: '" + strSelectedValue + "'";
    }, function() {
      document.querySelector('#user_spanOutput4').innerHTML = "Unable to write to clipboard.";
    });
    // https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API
    // Internet Explorer not supported
  }
});
document.querySelector('#user_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('#user_spanOutput4').innerHTML = "Copied: '" + strSelectedDisplay + "'";
    }, function() {
      document.querySelector('#user_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="user_spanResult5"> (waiting)</span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type='button' id='user_btnNote5'>Show Note</button><br />
Note:<br />
<span style="color:#0000aa;" id="user_spanResult5"> (waiting)</span>
<script>
document.querySelector('#user_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('#user_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="user_checkAll6()" style="margin: 0px 10px;">Check All</button>
<button type="button" onclick="user_uncheckAll6()" style="margin: 0px 10px;">Uncheck All</button>
</div>
<script>
function user_checkAll6(){
  const elCheckboxes6 = document.querySelectorAll('input[name="data\\[6\\].selects"]');
  for(let i = 0; i < elCheckboxes6.length; i++) {
    elCheckboxes6[i].checked = true;
  }
}
function user_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

Not available after v14.0

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="user_spanResult7"> (waiting)</span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<div style="text-align:right">
<span style="color:#0000aa;" id="user_spanResult7"> (waiting)</span>
<button type="button" onclick="user_countDays7()" style="margin: 0px 10px;"> << Count Days</button>
</div>
<script>
function user_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   = user_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('#user_spanResult7').style.borderBottom = strStyle;
  document.querySelector('#user_spanResult7').innerHTML = strMessage;
}
function user_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

Not available after v14.0

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="user_spanResult11"> (waiting)</span>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<div style="text-align:right">
<span style="color:#0000aa;" id="user_spanResult11"> (waiting)</span>
<button type="button" onclick="user_showDays11()" style="margin: 0px 10px;"> << Show Days</button>
</div>
<script>
function user_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  = user_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('#user_spanResult11').style.borderBottom = strStyle;
  document.querySelector('#user_spanResult11').innerHTML = strMessage;
}
function user_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

Not available after v14.0

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='user_btnAddDate7(this)'>+1y</button>
<button type='button' onclick='user_btnAddDate7(this)'>+1m</button>
<button type='button' onclick='user_btnAddDate7(this)'>+7d</button>
<button type='button' onclick='user_btnAddDate7(this)'>+1d</button> - 
<button type='button' onclick='user_btnAddDate7(this)'>-1y</button>
<button type='button' onclick='user_btnAddDate7(this)'>-1m</button>
<button type='button' onclick='user_btnAddDate7(this)'>-7d</button>
<button type='button' onclick='user_btnAddDate7(this)'>-1d</button>
<script>
function user_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 = user_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 user_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

Not available after v14.0

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='user_btnSetTime11(this)'>09:00</button>
<button type='button' onclick='user_btnSetTime11(this)'>09:30</button>
<button type='button' onclick='user_btnSetTime11(this)'>10:00</button>
<button type='button' onclick='user_btnSetTime11(this)'>13:00</button><br />
<button type='button' onclick='user_btnAddTime11(this)'>+60</button>
<button type='button' onclick='user_btnAddTime11(this)'>+10</button>
<button type='button' onclick='user_btnAddTime11(this)'>+1</button>,
<button type='button' onclick='user_btnAddTime11(this)'>-1</button>
<button type='button' onclick='user_btnAddTime11(this)'>-10</button>
<button type='button' onclick='user_btnAddTime11(this)'>-60</button>
<script>
function user_btnSetTime11(elBtn) {
  const elTime   = document.querySelector('input[name="data\\[11\\].time"]');
  elTime.value = elBtn.textContent;
}
function user_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  = user_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 user_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="user_quote0to1()"> Quote from String0 INQUERY </button>
<script>
function user_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

Not available after v14.0

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="user_convert7enUS19()" style="margin: 0px 10px;"> ↓ en-US </button>
<button type="button" onclick="user_convert7enUSLA19()" style="margin: 0px 10px;"> ↓ en-US2 </button>
<button type="button" onclick="user_convert7enGB19()" style="margin: 0px 10px;"> ↓ en-GB </button>
<button type="button" onclick="user_convert7enGBUTC19()" style="margin: 0px 10px;"> ↓ en-GB2 </button>
<button type="button" onclick="user_convert7jaJP19()" style="margin: 0px 10px;"> ↓ ja-JP </button>
<button type="button" onclick="user_convert7jaJPw19()" style="margin: 0px 10px;"> ↓ ja-JP2 </button>
</div>
<script>
function user_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 = user_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 user_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 = user_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 user_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 = user_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 user_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 = user_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 user_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 = user_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 user_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 = user_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 user_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

Count Files

Not available after v14.0

Referrer: FILES form (attached)

<div class="column column-1 " data-pdd-number="0">
  . . .
  <a href="/PE/Workitem/File/download?id=47100220&processDataInstanceId=47100177"
    title="Download" target="download" class="button icon notext"><span class="download">download:</span></a>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type="button" onclick="user_countFiles0()"> Count Files </button><div id="user_divResult0">(waiting)</div>
<script>
function user_countFiles0() {
  const elDivFilesArea = document.querySelector("div[data-pdd-number='0']");
  if ( elDivFilesArea === null ){
    document.querySelector('#user_divResult0').innerHTML = "Decoration Setting Error: not file type";
    throw new Error('Decoration Setting Error: not file type');
  }
  const elList = elDivFilesArea.querySelectorAll('input[name="data\[0\].selects"]:checked');
  document.querySelector('#user_divResult0').innerHTML = "Number of files to be posted: " + elList.length;
}
</script>

Capture

Workflow Decoration: Counts the number of attachments. Only checked files are counted. It is coded in vanilla Javascript.

Unzip Files

Not available after v14.0

Referrer: FILES form (attached)

<div class="column column-1 " data-pdd-number="0">
  . . .
  <a href="/PE/Workitem/File/download?id=47100220&processDataInstanceId=47100177"
    title="Download" target="download" class="button icon notext"><span class="download">download:</span></a>

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type="button" onclick="user_unzipFirstFile0()"> Unzip First File </button><div id="user_divResult0">(waiting)</div>
<style type="text/css">
a.dlbtn {
  border: 1px solid #000;
  border-radius: 0;
  background: #fff;
  margin: 0.5em;
  font-weight: 700;
}
a.dlbtn:hover {
  color: #fff;
  background: #000;
}
</style>
<script>
function user_unzipFirstFile0() {
  const elDivFilesArea = document.querySelector("div[data-pdd-number='0']");
  if ( elDivFilesArea === null ){
    document.querySelector('#user_divResult0').innerHTML = "Decoration Setting Error: not file type";
    throw new Error('Decoration Setting Error: not file type');
  }
  const elList = elDivFilesArea.querySelectorAll('input[name="data\[0\].selects"]:checked');
  if ( elList.length === 0 ){
    document.querySelector('#user_divResult0').innerHTML = "No file selected";
    throw new Error('No file selected');
  }
  const elFirst = elList[0];
  const elClosest  = elFirst.closest("div.process-data-file");
  const elDownload = elClosest.querySelector("a[title='Download']");
  console.log( "Download Uri " + elDownload.href );

  let arrStrFilenames = [];
  let arrBlobFiles = [];
  // js-dynamic-loading
  user_getScript('https://cdn.jsdelivr.net/npm/zlibjs@0.3.1/bin/unzip.min.js', function () {
    fetch( elDownload.href )
    .then( response => {
      if ( !response.ok ) {
        document.querySelector('#user_divResult0').innerHTML += " Network response was not ok";
        throw new Error('Network response was not ok');
      }
      return response.arrayBuffer();
    })
    .then( buf => {
      console.log( "ArrayBuffer byteLength: " + buf.byteLength );
      let byteArray = new Uint8Array( buf );
      // https://github.com/imaya/zlib.js/blob/develop/README.md#pkzip-1
      // https://github.com/imaya/zlib.js/blob/develop/README.en.md#pkzip-1
      let unzip = new Zlib.Unzip( byteArray );
      let filenames = unzip.getFilenames();
      console.log( "File and Directory: " + filenames.length );
      for( let i = 0; i < filenames.length; i++ ){
        if ( filenames[i].slice(-1) === "/" ) { continue; } // directory
        arrStrFilenames.push( filenames[i] );
        let blob = new Blob([unzip.decompress(filenames[i])],{type: "octet/stream"});
        arrBlobFiles.push( blob );
        console.log( "File: " + filenames[i] + " " + blob.size );
      }

      document.querySelector('#user_divResult0').innerHTML = "Downloadable Files: " +
                                                        arrStrFilenames.length + "<br />";
      for( let i = 0; i < arrStrFilenames.length; i++ ){
        // a href=xx download=yy 
        const newAtagBtn = document.createElement("a");
        const fileurl = URL.createObjectURL( arrBlobFiles[i] );
        newAtagBtn.innerHTML = "↓";
        newAtagBtn.href = fileurl;
        newAtagBtn.download = arrStrFilenames[i].split('/').pop();
        newAtagBtn.classList.add('dlbtn');
        document.querySelector('#user_divResult0').appendChild( newAtagBtn );
        // span
        const newSpan = document.createElement("span");
        newSpan.innerHTML = arrStrFilenames[i] + " (" + arrBlobFiles[i].size + " byte)";
        document.querySelector('#user_divResult0').appendChild( newSpan );
        // br
        const newBr = document.createElement("br");
        document.querySelector('#user_divResult0').appendChild( newBr );
      }
    })
    .catch(error => {
      console.error('There has been a problem with fetch operation: ', error);
      document.querySelector('#user_divResult0').innerHTML = "ZIP file checked? (eg: .zip .pptx .qar ..)";
    });
  }); // endof js-dynamic-loading

}
function user_getScript(scriptUrl, callback) { // for dynamic-loading
  const script = document.createElement('script');
  script.src = scriptUrl;
  script.onload = callback;
  document.body.appendChild(script);
}
</script>

Capture

Workflow Decoration: Unzips the ZIP file in your browser. Only the first file of the checked files will be decompressed. You can download the specified file in the archive. It is coded in vanilla Javascript.

QR Code Generation

Referrer: Singleline STRING form

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

Example of DESCRIPTION setting

vanilla JavaScript (click to open)
<button type="button" onclick="user_encodeToQrcode0()"> QR-Code Generation </button>
<div id="user_divResult0">(waiting)</div>
<script>
function user_encodeToQrcode0() {
  const strInput0 = document.querySelector( 'input[name="data\\[0\\].input"]' ).value;
  if ( strInput0 === "" ){
    document.querySelector('#user_divResult0').innerHTML = "No String";
    throw new Error('No String');
  }
  // js-dynamic-loading
  user_getScript('https://cdn.jsdelivr.net/npm/qrcode@1.4.4/build/qrcode.min.js',
            'sha256-DhdpoP64xch/Frz8CiBQE12en55NX+RhlPGRg6KWm5s=', function () {
    const opts = {
      errorCorrectionLevel: 'H', // L, M, Q, H
      type: 'image/png',
      width: 200,
      quality: 0.3,
      margin: 1,
      color: {
        dark:"#000",
        light:"#FFF0" // alpha channel (opacity) = 0
      }
    };
    QRCode.toDataURL( strInput0, opts, function (err, url) {
      if (err) throw err;
      let strHtml = '<a href="' + url + '" download="QR.png">';
          strHtml += '<img src="' + url + '" alt="QR Code" /></a>';
      document.querySelector('#user_divResult0').innerHTML = strHtml;
    });

  }); // endof js-dynamic-loading
}
function user_getScript(scriptUrl, integrity, callback) { // for dynamic-loading
  const script = document.createElement('script');
  script.src = scriptUrl;
  // Subresource Integrity (SRI) is a security feature that enables browsers to verify that
  // resources they fetch (for example, from a CDN) are delivered without unexpected manipulation.
  // https://developer.mozilla.org/en-US/docs/Web/Security/Subresource_Integrity
  script.integrity = integrity;
  script.crossOrigin = "anonymous"; // note: property name is "crossOrigin", not "crossorigin"
  script.onload = callback;
  document.body.appendChild(script);
}
</script>

Capture

QR Code Generation, Workflow Execution in Questetra BPM Suite

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#user_stripeTokenization {
  background: #666EE8;
  color: white;
  border-radius: 4px;
  font-size: 13px;
  margin: 6px;
}
button#user_stripeTokenization:focus {
  background: #555ABF;
}
button#user_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="user_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>
user_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('#user_card-element');

  card.addEventListener('change', function(event) {  // real-time validation
    var displayError = document.getElementById('user_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('user_card-errors');
        errorElement.textContent = result.error.message;
      } else {
        elTarget.value = result.token.id;
        // document.getElementById('user_card-success').textContent = "Token " + result.token.id;
        elTarget.readOnly = true;
        elTarget.style.backgroundColor = "#f2f2f2";
      }
    });
  });
});
function user_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
Scroll to Top