How to create your own Edit control plugin

PHPRunner 6.2 and ASPRunnerPro 7.2 add an exciting new feature - custom edit controls. You are longer limited by stock Edit controls that come with the software. And the best of all, creating new Edit controls is not complicated and we'll show how this can be done.

We will show you how to create ColorPicker and SignaturePad plugins. Before we proceed I recommend to check the following live demo that showcases both edit controls plugins. SignaturePad control works on mobile devices as well.



ColorPicker control

Lets say we want to add a color picker control that allows users select color the same way they do in Adobe Photoshop. Since our software comes with jQuery bundled we'll be searching web for "jQuery colorpicker". This search returns a number of results and the one we'll be using is miniColors. It looks nice and easy to integrate. Sources can be find at Github.

  • create a new folder under <Documents>\PHPRunnerPlugins\edit named ColorPicker
  • copy files EditMyField.js and EditMyField.php from 'MyField' folder to 'ColorPicker' folder
  • rename those files to EditColorPicker.js and EditColorPicker.php respectively
  • if you plugin needs extra files copy them to ColorPicker folder keeping folders structure
  • open EditColorPicker.js in any text editor and replace all occurences of 'EditMyField' with 'EditColorPicker'. Do the same with EditColorPicker.php file.
  • use addJSFiles() function in ColorPicker.php to add refeences to external Javascript files:

PHP

  1. $this->pageObject->AddJSFile("jquery.miniColors.min.js");

ASP

  1. this.pageObject.AddJSFile_p1 "jquery.miniColors.min.js"
  • use addCSSFiles() function to add CSS files

PHP

  1. $this->pageObject->AddCSSFile("jquery.miniColors.css");

ASP

  1. this.pageObject.AddCSSFile_p1 "jquery.miniColors.css"

In EditColorPicker.php file find buildUserControl() function. This is were you build HTML code for your control. If you leave predefined code as is it will display a simple text edit box. We only going add a minor change telling colorpicker control to use black color theme:

  1. class="black"

Lets see how we can turn this edit box into a colorpicker control. According to colorpicker instructions we need to call miniColors Javascript referencing edit box. We'll do so adding the following code to constructor function:

  1. $("#"+this.valContId).miniColors({
  2. letterCase: 'uppercase'
  3. });

letterCase option tells control to convert color values entered manually to upper case. this.valContId is the id of the control.

This is it, our control is ready. You can now launch PHPRunner, select ColorPicker as 'Edit as' type for any text field and enjoy your color picker on Add/Edit pages.

You may consider some additional enhancements.

1. It would be nice if instead of hex color value we can show some visual representation of selected color on List/View pages. We'll do so choosing 'View as' type 'Custom' and putting the following code there:

PHP

  1. $value="<span style='padding: 5px; background: ".$value."'>".$value."</span>";

ASP

  1. strValue="<span style='padding: 5px; background: " & strValue & "'>" & strValue & "</span>"

2. By default PHPRunner set focus to the first edit control when Add or Edit page is loaded. This is not a desired behaviour for colorpciker control as we do not want to see colorpicker popup window to open every time page is loaded. To prevent this from happening we'll implement setFocus function. Our job is to simply return false every time.

You you need to change control behaviour check all functions and events in source\include\common\runnerJS\Control.js file.

SignaturePad

The SignaturePad plugin allows to a add signature pad to your forms. SignaturePad works with both mouse and touch devices. We will be using SignaturePad jQuery plugin that comes with excellent documentation and examples.

The basic setup is the same: create new folder for SignaturePad plugin, copy and rename files, add files that plugin needs to plugin directory. This plugin is a bit more complicated and takes a few extra steps to integrate.

1. Build control's HTML code

Here is how we do this in buildUserControl() function:

PHP

  1. <div class="sigPad" style="width: '.($this->width+2).'px;">
  2. <ul class="sigNav">
  3. <li class="clearButton"><a href="#clear">Clear</a></li>
  4. </ul>
  5. <div class="sig sigWrapper">
  6. <div class="typed"></div>
  7.  
  8. <canvas class="pad" width="'.$this->width.'" height="'.$this->height.'"></canvas>
  9. <input id="'.$this->cfield.'" type="hidden" '
  10. .'name="'.$this->cfield.'" class="output">
  11. </div>
  12. </div>
  13.  
  14. ';

ASP

  1. dim str
  2. str = "
  3. <div class='sigPad' style='width: " & CStr(this.settings("width")+2) & "px;'>" & _
  4. "
  5. <ul class='sigNav'>" & _
  6. "
  7. <li class='clearButton'><a href='#clear'>Clear</a></li>
  8.  
  9. " & _
  10. "</ul>
  11.  
  12. " & _
  13. "
  14. <div class='sig sigWrapper'>" & _
  15. "
  16. <div class='typed'></div>
  17.  
  18. " & _
  19. "<canvas class='pad' width='" & this.settings("width") & "' height='" & this.settings("height") & "'></canvas>" & _
  20. "
  21. <input id='" & this.cfield & "' type='hidden' " & _
  22. "name='" & this.cfield & "' class='output'>" & _
  23. "</div>
  24. </div>
  25.  
  26. "
  27. ResponseWrite str
  28.  

2. Convert signature data to image

Signature data is recorded in JSON format as a sequence of lines and passed to the web server this way. Now we need to convert JSON data to PNG file and save it in 'files' folder on the web server. Luckily all the hard work was already done and all we need to do is to add a few lines of code to  readWebValue() function:

PHP

  1. if ($this->webValue) {
  2. // save signature to file
  3. require_once 'signature-to-image.php';
  4. $img = sigJsonToImage($this->webValue, array(
  5. 'imageSize' => array($this->width, $this->height)
  6. ,'bgColour' => $this->bgcolor
  7. ));
  8. $filename= $this->folder."/".generatePassword(15).".png";
  9. imagepng($img, $filename);
  10. $filesize = filesize($filename);
  11.  
  12. // prepare image info to be saved in db
  13. $result[] = array("name" => $filename,
  14. "usrName" => 'signature.png', "size" => $filesize, "type" => "image/png",
  15. "searchStr" => 'signature.png'.":sStrEnd");
  16. $this->webValue = my_json_encode($result);
  17. }

ASP

  1. this_object.getPostValueAndType
  2. if bValue(FieldSubmitted((CSmartStr(this_object.goodFieldName) & "_") & CSmartStr(this_object.id))) then
  3. doClassAssignment this_object,"webValue",prepare_for_db(this_object.field,this_object.webValue,this_object.webType,"","")
  4. else
  5. this_object.webValue = false
  6. end if
  7.  
  8. if Left(this_object.webValue,Len("data:image/png;base64,"))="data:image/png;base64," then
  9. this_object.webValue = Mid(this_object.webValue, Len("data:image/png;base64,")+1)
  10. end if
  11.  
  12. filename = generatePassword(15)
  13. var = Base64Decode(this_object.webValue)
  14. runner_save_file CSmartStr(getabspath(this_object.settings("folder"))) & "\" & filename & ".png" , var
  15.  
  16. set result=CreateDictionary()
  17. set result1 = CreateDictionary()
  18.  
  19. setArrElement result,"name",this_object.settings("folder") & "/" & filename & ".png"
  20. setArrElement result,"usrName","signature.png"
  21. setArrElement result,"size",LenB(var)
  22. setArrElement result,"type","image/png"
  23. setArrElement result,"searchStr","signature.png" & ":sStrEnd"
  24. set result1(0) = result
  25. this_object.webValue = my_json_encode(result1)
  26.  
  27. if not (IsFalse(this_object.webValue)) then
  28. setArrElement avalues,this_object.field,this_object.webValue
  29. end if

You can read more info JSON to image conversion here.

Note the way how file info is stored in the database. Since new version offers multiple files upload we need to be able to store more info there than just file name. Besides the file name itself we also save file size, file type and path to the file in JSON format. Here is how typical file upload field looks in the database:

  1. [{"name":"files\/h8hsoz5hd23b0ik.jpg","usrName":"Chrysanthemum.jpg","size":879394,"type":"image\/jpeg","searchStr":"Chrysanthemum.jpg:sStrEnd"},
  2. {"name":"files\/2p85jz854o6fbv8.jpg","usrName":"Desert.jpg","size":845941,"type":"image\/jpeg","searchStr":"Desert.jpg:sStrEnd"},
  3. {"name":"files\/pm4fu8uv2u6xc1w.jpg","usrName":"Hydrangeas.jpg","size":595284,"type":"image\/jpeg","searchStr":"Hydrangeas.jpg:sStrEnd"}]

3. Customization

Now it's the time to customize our plugin. Users may need to change the appearance and behaviour of signature pad i.e.

  • change width and height of signature pad
  • change background color
  • change folder where image files are stored
  • make signature pad field required

As a first step we need to learn to pass settings from PHPRunner wizard to plugin. Proceed to "Edit as" dialog in PHRRunner and click 'Add initialization script' button. Here is the sample set of settings of SignaturePad control:

PHP

  1. // signature field height
  2. $this->settings["height"] = 100;
  3. // signature field width
  4. $this->settings["width"] = 300;
  5. // signature background color
  6. $this->settings["bgcolor"] = array(0xff, 0xff, 0xff);
  7. // set it to true to make signature field required
  8. $this->settings["required"]=false;
  9. // folder to store signature files
  10. $this->settings["folder"]="files";

ASP

  1. ' signature field height
  2. this_object.settings("height") = 100
  3. ' signature field width
  4. this_object.settings("width") = 300
  5. ' signature background color
  6. this_object.settings("bgcolor") = "#FFFFFF"
  7. ' set it to true to make signature field required
  8. this_object.settings("required")=false
  9. ' folder to store signature files
  10. this_object.settings("folder")="files"

This code is self-descriptive, you can pass any number of settings there. If you create your own edit control plugin place sample initialization script to sample.php file that needs to be located in the plugin folder.

Now we can access those settings in plugin's initUserControl() function. We can also pass settings to Javascript part of the plugin.

PHP

  1. // setting default value
  2. $this->required = false;
  3.  
  4. // saving settings to the local variable
  5. if ($this->settings["required"])
  6. $this->required=$this->settings["required"];
  7.  
  8. // passing settings to Javascript
  9. $this->addJSSetting("required", $this->required);

ASP

  1. this.addJSSetting_p2 "required", this.settings("required")

Now let's actually add some new functionality

Making signature field required

In Javascript init() function add the following code:

  1. if (this.required)
  2. this.addValidation("IsRequired");

Signature is not required by default. To make it required add the following line of code to initialization script under 'Edit as' properties:

PHP

  1. $this->settings["required"]=true;

ASP

  1. this_object.settings("required")=true

Setting width and height of signature pad

Passing width and height from 'Edit as' settings in PHPRunner:

PHP

  1. $this->settings["height"] = 100;
  2. $this->settings["width"] = 300;

ASP

  1. this_object.settings("height") = 100
  2. this_object.settings("width") = 300

Then we can use $this->width and $this->height in buildUserControl() function to specify width and height of our control:

<canvas class="pad" width="'.$this->width.'" height="'.$this->height.'"></canvas>

Changing folder where signature images stored

Passing folder name from 'Edit as' settings in PHPRunner:

PHP

  1. $this->settings["folder"]="files";

ASP

  1. this_object.settings("folder")="files"

Using this variable in readWebValue() function:

PHP

  1. $filename= $this->folder."/".generatePassword(15).".png";

ASP

  1.  
  2. filename = generatePassword(15)
  3. var = Base64Decode(this_object.webValue)
  4. runner_save_file CSmartStr(getabspath(this_object.settings("folder"))) & "\" & filename & ".png" , var
  5.  

Changing signature pad background color

Passing background color from 'Edit as' settings in PHPRunner:

PHP

  1. $this->settings["bgcolor"] = array(0xff, 0xff, 0xff);

ASP

  1. this_object.settings("bgcolor") = "#FFFFFF"

bgcolor array contains color value in RGB format (Red, Green, Blue, each color ranges from 0 to 255, 0xff is a hexadecimal representation of 255. array(0xff, 0xff, 0xff) means white color.

Now in Javascript control constructor function we can use this.bgColor to pass background color to SignaturePad control:

  1. $('.sigPad').signaturePad({drawOnly:true, bgColour: this.bgColor});

We also need to pass backgound color to sigJsonToImage() function that converts JSON signature data to image. We use $this->bgcolor variable here in readWebValue() PHP function.

PHP

  1. $img = sigJsonToImage($this->webValue, array(
  2. 'imageSize' => array($this->width, $this->height)
  3. ,'bgColour' => $this->bgcolor
  4. ));

This is it. As you can creating your own edit control plugins is not a rocket science and you can build something useful in just a few lines of code.

Lets us know what kind of edit controls you want us to implement. If you have one in mind feel free to post detailed description here and provide some links to sample implementation.

Developer notes

File naming conventions

Your edit plugin might need to utilize some additional PHP, JS and CSS files. Files can be added to the main plugin folder or to subfolders like "include" or "img". Files from the main plugin directory will be copied to the output directory. Files from "include" directory will be copied to "/include" etc. Considering the fact that your application may use multiple plugins we suggest providing unique names to helper files. For instance, if your plugin name is Slider naming CSS file slider.css is a good idea.

Inline edit considerations

To make sure edit control content is not wrapped while in inline edit mode we recommend to enclose the whole control into a <div> tag. This needs to be done in buildUserControl function in PHP or ASP code.

Access to field properties

In some situations you might need to access database field properties i.e. to find this field type. Here is PHP code that does the job:

PHP

  1. global $strTableName;
  2. $pSet = new ProjectSettings($strTableName);
  3. if(IsDateFieldType($pSet->getFieldType($this->field)))
  4. {
  5. $this->webValue = "2000-01-01 ".$this->webValue;
  6. }

ASP

  1. if(IsDateFieldType(this_object.pageObject.pSetEdit.getFieldType_p1(this_object.field))) then
  2. this_object.webValue = "2000-01-01 " & this_object.webValue
  3. end if

Cleaning up

If your plugin creates popup you need to destroy them properly. The best option is to implement a destructor of Javascript control destroying all previously open windows. An example from BootstrapTimepicker control:

  1. destructor: function(){
  2. // call parent
  3. Runner.controls.EditBootstrapTimepicker.superclass.destructor.call(this);
  4. $("#"+this.valContId).timepicker('hideWidget');

Using z-index property

We suggest to avoid using z-index CSS property in your custom controls to minimize interference with built-in functionality like popup windows. If you absolutely must to use this property make sure the top most container of your control has z-index of 0.

5 comments to How to create your own Edit control plugin

Leave a Reply

 

 

 

You can use these HTML tags

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>