Jumat, 20 Maret 2026

Submit HTML Form using Javascript with Validation

My last post was almost a year ago and I stopped posting since I got to know chatGPT. instead of googling around I can easily ask chatGPT and got the answer that I needed. Furthermore, I learned how to vibe code as well. Therefor I have more reasons to stopped posting. A while ago I remember again the reason why I wrote this blog, it helps me recall the things that I need. I'm such a forgetful person. 

Ok, lets start. It's about submiting a HTML form using javascript but it has to be validated before submitted. The code is quite simple. The validation function is a native function from HTMLelement. 

with native javascript, it will look like this: 

  
    function submitWithValidation(){
      var form = document.getElementById('myForm');

      if (!form.checkValidity()) {
          form.reportValidity(); 
          return; // STOP submit
      }

      //next logic

      form.requestSubmit();

    }
  


If you use JQuery, then the code will look like this:

	
    function submitWithValidation(){
      var form = $("#myForm");

      if (!form[0].checkValidity()) {
          form[0].reportValidity(); 
          return; // STOP submit
      }

      //next logic

      form[0].requestSubmit();

    }
    
    

Why we need that index when using the JQuery, because JQuery selector returns JQuery collection / object and we need to select the first element. Why we have to do that? because these functions:

  • checkValidity()
  • reportValidity()
  • requestSubmit()

are native javascript functions, so they need a DOM element.

document.getElementById() returns a DOM element.  

Selasa, 29 April 2025

PDF Digital Signature using PyHanko with Custom QR Code Image Stamping

For those who are in the middle of searching for a free tools to put digital signature on a PDF file, here are two options that I had ever tried to use :

  • lsnepomuceno/laravel-a1-pdf-sign. It is a plugin for laravel and written in PHP. This library inherits methods from FPDI and FPDI inherits some methods from TCPDF. The documentation is quite easy to understand and there are several examples how to use it to sign PDF file. The drawbacks are, first it does not provide any function to validate the signature and data integrity. Second, this library does not let you to sign the PDF file incrementally. Well, I customized the code so I can check the validity of the signature and the PDF file's integrity. But I still failed to make this library to allow the PDF File being signed incrementally. At this point I stopped trying customizing this library and look for an alternatives with following requirements:
    • it should be an executable script (Go, bash, python, etc...)
    • it should be able put a custom QRcode image for the stamp
  • Python Pyhanko. My search ended with PyHanko. It is an cli, so it matches with my first requirement. But...I was still not sure whether it can satisfy my second requirement. 

I forget to mention, pyhanko is able to generate QRcode as well for the stamp. But what I need is I want to put a logo on the QRcode image. Unfortunately pyhanko cannot do that. That's why I put "custom" QRcode on this post's title. 

So...after several attempt, asking chatGPT and Gemini I still could not find any solution. And this is the lesson learned....if chatGPT and Gemini can not help you any further, try to read the documentation diligently hehehe....so the solution is right over there.

Again, for those who are looking for Digital Signature tool for PDF that allow you to sign it incrementally and put a custom QRcode for the Stamp.....here are the steps that might help you:

For your information, my server is ubuntu

1. install python (latest version):    

    sudo apt install python3

2. make a virtual environment for python 

    python3 -m venv /path/to/virtual-env

3. activate the virtual environment

    source /path/to/virtual-env/bin/activate

4. install pyhanko latest version (0.26.0) and Pillow 

    pip install pyhanko==0.26.0

     pip install Pillow

5. go to your project directory 

    cd /path/to/your/project/pyhanko

6. prepare the pdf file that you want to sign, the QRcode image and the pkcs12 file (.pfx)

7. I put my passphrase for .pfx file inside a text file. I named it "mypass"

8. make a config file here, for example pyhanko.yml. Put this config inside:

    stamp-styles:
        justqr:
            type: text
            stamp-text: ""
            border_width: 3
            background:  "/path/to/your/project/pyhanko/myqrcode.png"
            background-opacity: 1

 

7.  sign the PDF file using this command (I used pkcs12, if you use another method you can adjust the signing method)

PYHANKO_CONFIG=pyhanko.yml pyhanko sign addsig \
    --no-strict-syntax \
    --field 1/200,10,300,110/sig1 \
    --style-name justqr \
    pkcs12 \
    --passfile mypass \
    to_sign.pdf \
    signed.pdf \
    mypkcs12.pfx

 

--no-strict-syntax : well...it was a help from chatGPT hehehe...there was an error and this is the solution hehe

--field page/x1,y1,x2,y2/nameOfSigField: --field is to define the location where you want to put the stamp.

    page: the page number

    x1,y1 define the coordinate of the bottom left edge of the stamp 

    x2,y2 define the coordinate of the top right edge of the stamp

    nameOfSigField: it will be used to put the coordinate in byte of the signature. I put sig1 for the first signature, sig2 for the second signature and so on. 

I'm sure that the other options are self explained, right? 

The stamp will looks like this, FYI the QRcode image was generated by another tools

 



If you want to have a border less QR code image, then change the value of border_width to 0 (zero) on the config file for the stamp-style.

Oh if you want to put QRcode and sometext beside the QRcode, for example the name of the signer and the timestamp when it is signed, you can change the config file into this.

stamp-styles:
  qrandtext:
        type: text
        stamp-text: "Signed by \n. %(signer)s on \n%(ts)s"
        background: "/path/to/project/pyhanko/myqrcode.png"
        background-opacity: 1
        background-layout:
          x-align: left
          margins:
            left: 10
            top: 10
            bottom: 10
        inner-content-layout:
          x-align: right
          margins:
            right: 20

 then change the value of --style-name options to "qrandtext" on the cli command:

 PYHANKO_CONFIG=pyhanko.yml pyhanko sign addsig \
    --no-strict-syntax \
    --field 1/200,10,500,110/sig1 \
    --style-name qrandtext \
    pkcs12 \
    --passfile mypass \
    to_sign.pdf \
    signed.pdf \
    mypkcs12.pfx

 

your stamp will look like this


 

From the config file I'm sure you can recognize that I use the background to display the custom QRcode. I set the opacity to 1 so it will be shown as a solid image.  

 I hope this help you somehow.

Kamis, 14 Desember 2023

javascript forEach on json object

 For everyone who is fucked up with forEach on JSON object. 

Find solution in this link

https://codedamn.com/news/javascript/how-to-fix-typeerror-foreach-is-not-a-function-in-javascript

or something like this

 

                        var myval = JSON.parse(results);


                        Object.entries(myval).forEach(entry => {
                            [key, value] = entry;
                            console.log(entry);
                        });

Sabtu, 17 Juni 2023

PHP Timestamp Jakarta

Just for my personal purpose to remind me something easy but easily forgettable as well. Here is how we get timestamp for jakarta.

ini_set('date.timezone', 'Asia/Jakarta');
$ts = date('Y-m-d H:i:s');

Jumat, 04 Februari 2022

Datatable: set title to downloaded File

 Short post, in case I need it later. 

So my problem was, I have several datatables in one page and each datatable has download buttons. Normaly, datatable will use the page's title as the name of the downloaded file. But I have more than one datatables and I want the downloaded file has different name. 

And here is the solution.


$('#zero_configuration_table').DataTable( {
	dom: 'Bfrtip',
	buttons: [
		{extend:'excelHtml5', title: 'Dashboard Tracer Study'},
        {extend:'pdfHtml5', title: 'PDF Dashboard Tracer Study'}
	],
	scrollX:        true,
	scrollCollapse: true,
	paging:         false,
	fixedColumns: false,
	autoWidth: false,
});

Take a look at the buttons, simple right. I can even put different name on each button. With that code, the datatables doesn't do pagination and it is horizontally scrollable.

Datatable : Adding a Row Dynamically and adding its atrribute

Ok, I had a problem to solve the problem I mentioned in the title of this post. 

So, I combined two solution from two sources (Actually I've browsed to several websites and discussions). 

These are my sources: Source 1, Source 2.

I use ajax to retrieve the data and then add them dynamically to the table. Then, I want to align the text to center and add onclick event on each row.

So here is my Table:


<div class="table-responsive">
	<table class="table table-striped table-bordered" 
    	id="transaction_detail" cellspacing="0" width="100%">
		<thead>
			<tr class="text-center align-middle">
				<th>Name</th>
				<th>email</th>
				<th>Phone</th>
				<th>Transactions</th>
				<th>Turnover</th>

			</tr>
		</thead>
		<tbody >

				
		</tbody>
	</table>
</div>


And here is my Ajax:


$.ajax({
  type:"POST",
  url:"/gettransaction",
  data:{customer_id: customerid},
  success:function(data){
	var jsondat = JSON.parse(data)  ;
	
	//clear the table's body
	$("#transaction_detail").DataTable().clear().draw();

	if(jsondat.length > 0){
		for(var i=0; i<jsondat.length; i++){
			
			var rowTab = $("#transaction_detail")
				.DataTable()
				.row
				.add([
				jsondat[i].customer_name,
				jsondat[i].customer_address,
				jsondat[i].customer_phone,
				jsondat[i].number_transaction,
				jsondat[i].turnover
			]);


			//use node() so that row is editable.
			var rowEdit = rowTab.node();

			$(rowEdit).attr("style", 
				"cursor:pointer; text-align:center");
			$(rowEdit).attr('onclick',
            	"showTrans("+jsondat[i].customer_id+")");

			//redraw the table after its modified
			rowTab.draw(false);
		}   

	}
  },
  error: function(){

  }
});


I hope it can help you somehow. cheers!!

Sabtu, 15 Januari 2022

datatable: show row per page and export button at the same time

Well this posting is an extra info of my previous posting. After I struggled with an error, now I want to show the page per button and the export button at the same time. 

I found two ways from stackoverflow

so here is the first solution:


$(document).ready(function() {
    document.title = 'page Title';
    $('#example').DataTable( {
        dom: 'Bfrtip',
        lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "All"]],
        buttons: [
            'pageLength',
            'copyHtml5',
            'excelHtml5',
            'csvHtml5',
            'pdfHtml5'
        ],
    } );
} );

You can delete or comment the second line, it was included in my code since I coded it in a team and the used template seems doesn't have title tag in its header. So, I set it in here. The title of the page will be used as the filename when its downloaded. 

The second solution is:


$(document).ready(function() {
    document.title = 'page Title';
    $('#example').DataTable( {
        dom: 'lBfrtip',
        lengthMenu: [[10, 25, 50, -1], [10, 25, 50, "All"]],
        buttons: [
            'copyHtml5',
            'excelHtml5',
            'csvHtml5',
            'pdfHtml5'
        ],
    } );
} );

Take a look at the 'dom:' attribute. The second solution uses 'lBftrip' whereas the first solution uses 'Bfstrip'. now then take a look closer to the first solution, if we use 'Bfstrip', then we have to add 'pagelength' as a button as well. 

Just try them and see the different. NOTE!!! don't forget to call all the needed css and js scripts. You can find them all here.

Datatable Error : Uncaught TypeError: $(...).DataTable is not a function

 It was really pain in the ass to look for a solution for that error. But, finally I found it.

Here is the solution: Use defer to call the datatable script and its other following scripts. 

I needed to use datatable with export button, I get the examples code from here.

Here was how I called the scripts that gave me that error:


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></script>
<script type="text/javascript"  src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js" ></script>
<script type="text/javascript"  src="https://cdn.datatables.net/buttons/2.1.0/js/dataTables.buttons.min.js" ></script>
<script type="text/javascript"  src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js" ></script>
<script type="text/javascript"  src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js" ></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js" ></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/2.1.0/js/buttons.html5.min.js" ></script>


And how it was fixed:


<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js" ></script>
<script type="text/javascript"  src="https://cdn.datatables.net/1.11.3/js/jquery.dataTables.min.js" defer></script>
<script type="text/javascript"  src="https://cdn.datatables.net/buttons/2.1.0/js/dataTables.buttons.min.js" defer></script>
<script type="text/javascript"  src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.1.3/jszip.min.js" defer></script>
<script type="text/javascript"  src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/pdfmake.min.js" defer></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.1.53/vfs_fonts.js" defer></script>
<script type="text/javascript" src="https://cdn.datatables.net/buttons/2.1.0/js/buttons.html5.min.js" defer></script>

I found the solution in this forum and here is the link that explains how defer works.

Kamis, 31 Desember 2020

Get Date of 1 month Ago with PHP

 Hi again, at the first day of the year 2021 I wrote this post since my web app showed error while retrieving data between the date of one month ago until today. 

So here is the way to get date of 1 month Ago.

	
    	$dateHelp = date("Y-m-d");
        $monthAgo = Date("Y-m-d", strtotime($dateHelp."-1 Month"));
    


To get the date of  N months later / ago, just change the text "-1 Month" to "+N Month" to get N months later or "-N Month" to get N months ago.

Here is the source where I read the solution. Source

Minggu, 30 Agustus 2020

Save PNG image from HTML5 Canvas (the correct way, proved working!!)

This post is kind of a continuation of my previous post 'Take A Picture From Webcam With HTML5'. I had then an issue how to save the image localy. The image taken from the webcam is saved in base64 encoded data with this format data:image/png;base64,AAAFBfj....[base64 encoded data]

After I googled around, the most solution that I found told me just seperate the base64 data from that format and decode it directly to save the image. Unfortunately, its not that easy!!!

shortly, I'll show you how to do it correctly. This solution is shown here. Thanks mas bro Fazlurr!! you are the best.

again, I developed the application using Codeigniter and the code I show here is the function to save the image localy. This function is called by an AJAX function. 



function saveImage(){
     $img = str_replace('data:image/png;base64,', '', $_POST['data']);
     $img = str_replace(' ', '+', $img);
     $data = base64_decode($img);
     $file = FCPATH.'/image/page/'.$_POST['name'].'.png';
     $success = file_put_contents($file, $data);
     echo $success ? '1' : '0';
}



the AJAX send  two POST data; the image data taken from canva and the name used for this image. Take a look at the third line, this line is the key. Other solutions found in google don't have this line, so most of them failed to save the image correctly. 

Well, the funny thing is that I know it works but I don't know what does that third line do, so dont ask me why this code works...ehehehe....

Kamis, 16 Juli 2020

scrollbar Bootstrap Modal

The real tittle is actually "how to make second shown Modal scrollbar". I have two modal on one page. The second modal should be shown as the result of ajax response sent in the first modal, so the first modal will be hidden and followed by showing the second modal. The second modal has a length, that it needs to be scrolled up and down. The problem was the scrollbar does not work for that modal, instead the scrollbar was functionable for the parent page.

So here is the solution:

 

<div class="modal fade" id="myModal"  role="dialog" aria-hidden="true" style="overflow-y: initial !important">
    <div class="modal-xl modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content">
            <div class="modal-header">
                ...
            </div>
            <div class="modal-body" >
                ... 
            </div>

        </div>
    </div>
</div>


Take a look at style="overflow-y: initial !important". This is the solution.

Select2 problem in Bootstrap Modal

Its a common problem implementing select2 in Bootstrap Modal. Mostly you will face problem that either the dropdown menu shown behind the modal or the livesearch doesn't work.

I found the solution after I browsed around, unfortunately I forgot the source where I found this solution. What I remembered, blurly, I found it in Github.

So, if my HTML Bootstrap Modal looks like this:

 
<div class="modal fade" id="myModal"  role="dialog" aria-hidden="true">
    <div class="modal-xl modal-dialog" role="document">
        <div class="modal-content">
            <div class="modal-header">
                ...
            </div>
            <div class="modal-body" >
                <div class="form-group">
                    <label for="idMySelect">SELECT</label>
                    <select id="idMySelect" class="form-control basic">
                        <option value="one">option one</option>
                        <option value="two">option two</option>
                        <option value="three">option three</option>
                        ...
                    </select>
                </div> 
            </div>

        </div>
    </div>
</div>


the JS for select2 in that modal would be:

 
$("#idMySelect").select2({
     tags: true,
     dropdownParent: $('#myModal')
});

We should set each select2 separately, if we have more than one select2 and especially if those select2 are in different modal (if we use more modals in one page) or some are on the parent page.

Selasa, 14 Juli 2020

Take Picture From Webcam With HTML 5

HTML5 has a super cool feature, that enables us to access the media installed in our PC. During developing a web app, I surprised with two things, which are already wellknown for most people maybe. But for me they are new and its really good to know.

My app has to take pictures and save them as PDF, but those pictures should not be saved. So first thing, here is my code to take pictures from a web using a webcam.

Here are my sources. Sumber 1 dan Sumber 2

HTML

 
<style>
.videoElement {
 width: 400px;
 height: 275px;
 background-color: #666;
    transform: rotateY(180deg);
    -webkit-transform:rotateY(180deg); /* Safari and Chrome */
    -moz-transform:rotateY(180deg); /* Firefox */
}
</style>

<video autoplay="true" id="video-webcam" class="videoElement" style="text-align:center">
   Izinkan untuk Mengakses Webcam untuk Demo
</video>


<img id="snapshot" style="width: 400px;height: 275px;">                          

<button onclick="takeSnapshot()"> Take Picture </button>
                            


And here is the JS code:

 
var video = document.querySelector("#video-webcam");

navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.oGetUserMedia;

if (navigator.getUserMedia) {
    navigator.getUserMedia({ video: true }, handleVideo, videoError);
}

function handleVideo(stream) {
    video.srcObject = stream;
    //console.log(stream);
}

function videoError(e) {
    // do something
    alert("Izinkan menggunakan webcam untuk demo!")
}

function takeSnapshot() {
    var img = document.getElementById('snapshot');
    var context;
    var width = video.offsetWidth
            , height = video.offsetHeight;

    canvas = document.createElement('canvas');
    canvas.width = width;
    canvas.height = height;

    context = canvas.getContext('2d');
    context.drawImage(video, 0, 0, width, height);

    img.src = canvas.toDataURL('image/png');
    img.style="transform: scaleX(-1);width: 400px;height: 275px";

}


What I learnt from that code are:
  1. The display taken from webcam has to be mirrored, as well as the picture taken. I did it with the CSS above.
  2. The images, that are taken using canva, are saved in Base64 code. This is super cool, furthermore the HTML tag is able to show an image with source of Base64 code. Super cool.... this feature helps me a lot, because I don't have to save the picture in server. What I did was I took this Base64 code and put them in HTML tag, which the HTML code is later converted to PDF file

Thats all, folks

Sabtu, 13 Juni 2020

Transparent Background (Modal Loader)

Quick post. I want to show a loader, that block the whole page and it should not be closeable, while waiting for AJAX response. I use modal and loader image then I set the modal background to transparent.

To do it, I read from this link_1 and link_2.


 
<div class="modal fade" id="loaderModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true" data-backdrop="static" data-keyboard="false">
    <div class="modal-dialog modal-dialog-centered" role="document">
        <div class="modal-content" style="background-color:rgba(0, 0, 0, 0.0);">
            <div class="modal-body">
                //replace with gif loader image
                <div class="loader dual-loader mx-auto"></div>
                <div class="row">
                    <div class="col-xl-12 col-md-12 col-sm-12 col-12" style="text-align:center; color:black">Loading...</div>
                </div>
            </div>
        </div>
    </div>
</div>

Jumat, 12 Juni 2020

Javascript konversi angka ke format rupiah

thanks to faisalman  who provides this incredible javascript. 
Javascript yg membantu kita mengkonversi angka ke format rupiah dan sebaliknya, script yg sangat membantu sekali. Recomended utk di bookmark. Ini linknya

PHP Set session timeout

Quick post. This post will help me to recall how to set a session timeout in PHP someday. Lets cut the explanation what is actually happening behind the scene in PHP for timing out the session. As my other posts, I will put the source where I read this great and helpfull solution. Link. I'd like to thank the dude who wrote that post.

So, I'm still using CodeIgniter and I put this function on my Model for login. So here is my function:


    function session_timeout_check()
    {
        
        $timeout_max = 1800;//timeout after 30 minutes
        $time = $_SERVER['REQUEST_TIME'];

        if(isset($_SESSION['LAST_ACTIVITY']))
        {
            if($time - $_SESSION['LAST_ACTIVITY'] > $timeout_max)
            {
                return 1;
            }
            else
            {
                $_SESSION['LAST_ACTIVITY'] = $_SERVER['REQUEST_TIME'];
                return 0;
            }
        }
        else
        {
            return 1;
        }
    }

I put that function in the constructor of all controller:


    public function __construct()
    {    
        parent::__construct();
        $this->load->model(array("M_login"));
        session_start();
        if($this->M_login->session_timeout_check() == 1)
        {
            //unsetting session variable, destroying session and redirecting to login page
        }
    }

inside the if you can put other conditions to check the session.

so that's all folks.

Senin, 27 April 2020

AJAX in JQuery

Again, it is just a quick post that helps me recall something that I forget easily. Here is the syntax for AJAX in JQuery. I have seen 2 types of AJAX syntax in JQuery, for me this syntax is much easier to understand.


$.ajax({
            type:"POST",
            url:"urlToAjax.php",
            data:{
              "data1":dat,
              "data2":dat2 
            },
            success : function(results) {
              console.log(results)
              //any code if succeed goes here 
            },
            error : function(res){
              console.log(res)
              //any code to generate error report goes here
            }
  });


The code above sends Request using POST.

That's all folks.

Kamis, 09 April 2020

Creating JSON data in Javascript

Quick post about how to create JSON data in javascript.
I want to POST some inputs via AJAX but I want send them just in one variable, don't ask me why. I just want to do it that way.

here is my HTML code

<input id="name" type="text">

<input id="phone" type="text">

<input id="address" type="text">

I want send them as JSON data, here is how I do it:


var obj = new Object();
obj.name = document.getElementById('name').value;
obj.phone= document.getElementById('phone').value;
obj.address= document.getElementById('address').value;

var myData = JSON.stringify(obj);


That's it. the variable myData is the json data.

Rabu, 04 September 2019

2 Dimensional Array to JSON data in Javascript

Quick posting on how to convert 2 dimensional javascript array to JSON data. Source!
  
var questions = [];
 
 for(i=0;i<3;i++) {
    questions[i] = {};
    questions[i]["question"] = "hey";
    questions[i]["rating"] = "123";
 });


var encoded = JSON.stringify(questions);
console.log(encoded);

Take a look at the third code line! With this way, you send the second array dimension as array object. If you send this data with AJAX to a PHP code, you should put 'true' as the second argument on json_decode php function. It will convert the JSON data into a php array.
  
<?php

$myarray = json_decode(encoded, true);

?>