【Publisher】Extensibility using HTML, CSS and JavaScript

# Introduction #
I will customise the standard Sharperlight web report.
The report will have two buttons and a check box on each row of a table.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/35b525dc-2760-e67e-8a21-e5f16d9c01e0.png)

I use HTML, CSS and JavaScript to make it.

# Backend Code #
The backend code is written as a HTML file and it has the button elements and JavaScript code.
This code will be rendered as a part of the web report generated by Sharperlight engine so the page has a reference to JQuery library. This is the reason why this `$("input[name*='selectedDocuments']")` can be used.

This code creates two buttons at the top of report contents, and when they are clicked, the checkbox on each row is ticked or unticked.

The checkbox is created with a sharperlight expression.
```
<script>
    function btApprSelectAll_click(source) {
        try{
            _toggle_Selection(true);
        }catch (err){
            throw 'Error on btApprSelectAll_click(): ' + err.message;
        }
    };
    
    function btApprDeselectAll_click(source) {
        try{
            _toggle_Selection(false);
        }catch (err){
            throw 'Error on btApprDeselectAll_click(): ' + err.message;
        }
    };

    function _toggle_Selection(state){
        try{
            // When buttons are outside of the iframe where the table is in.
            $("input[name*='selectedDocuments']").prop("checked", state);
        }catch (err){
            throw 'Error on _toggle_Selection(): ' + err.message;
        }
    };
    
</script>
    
<div id='buttonBox'>
    <div><input class='button buttonHeaderC1R1 button1' id='btApprSelectAll' type='button' value='Select All' onClick='btApprSelectAll_click(this)' /></div>
    <div><input class='button buttonHeaderC2R1 button2' id='btApprDeselectAll' type='button' value='Deselect All' onClick='btApprDeselectAll_click(this)' /></div>
</div>
```
As I said, this code is a HTML file so it has to be imported to a published report.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/5552140d-12f7-075d-3938-27717bb89012.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/9e2476e9-8017-0a03-5ce2-cb74c81bb649.png)
The reference code is set here.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f791a7a1-9b86-927b-4cab-37ce3fa13c11.png)
It is like this.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/43e92fda-0f65-3599-7c3f-a07037de03a1.png)
```
<!--ReportContentSectionBegin-->
<ResourceImport=RS10130806/>
<!--ReportContentSectionEnd-->
```
The Sharperlight specific control tag `<!--ReportContentSectionBegin-->` means **Please render the content of the imported HTML code into the report content section.**
This is the **Report Content Section**.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/6b34f68e-2b3c-a6e6-75b4-cb5f4b843b7c.png)

# The CheckBoxes #
The checkboxes are created in the query of the report.
The web report must have a query definition so it can be defined with the Query Builder.
Let's open it with this button.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/bcc6a4c3-13d4-c607-20cf-a9d36a00fd9a.png)

I defined this query and it uses SAP Business One datamodel(Product).
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/7ecca0a4-2dae-4121-de4d-47a2a3b24adb.png)
Notice the first output item, which creates a checkbox.
It is Sharperlight Expression, and it is an HTML input element definition.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/36d5c495-54f6-3922-a74c-6a9e413b8a71.png)
```
"<input type='checkbox' id='" +  "docNumber" + {%DocNum}
+ "' data-docNumber='" + {%DocNum}
+ "' name='selectedDocuments' value='" + {@Company}
+ "' style='width:20px;height:20px'>"
```
As you can see, there are some Control Tags such as `{%DocSum}` and `{@Company}`.
They are reference code to the other output item and the filter item, and they are replaced with their value at runtime.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/f5baa960-51e6-163e-d6ea-60da2161afec.png)

# CSS #
The buttons defined in the HTML code imported need the class definition.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/eb1718d9-5bdb-f9f8-c191-b9177cea3f20.png)
It can be done here.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/b47d6be2-7883-99e7-191c-0754b93f46d7.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2530698/5bc428af-bcd0-ddd4-ae1d-281725951781.png)
```
<style type="text/css">
#slBody{
	margin-left: 10px;
}
#sectionHeader{
	display: block;
}
#contentAlignLeft{
	margin-top:65px;
}
#buttonBox{
	position:absolute;
	left: 0px;
	top: 2px;
}



/* This is required when the fucntion buttons are displayed on Safari */
input[type="button"] {
     -webkit-appearance: none;
}
/* This is required when the fucntion buttons are displayed on Safari */

body{
	font-family: Monospace;
}
.button {
	width: 80px;
    	height: 50px;
    	padding: 8px;
  	font-size: 12px;
  	cursor: pointer;
  	text-align: center;
  	text-decoration: none;
  	outline: none;
  	color: #fff;
  	border: none;
  	border-radius: 10px;
  	box-shadow: 0 5px #999;
}
.buttonHeaderC1R1{
	position:absolute;
    	left: 10px;
}
.buttonHeaderC2R1{
	position:absolute;
	left: 100px;
}
.buttonHeaderC1R2{
	position:absolute;
	left: 190px;
}
.buttonHeaderC2R2{
	position:absolute;
	left: 280px;
}

.button1{
	background-color: #ED4C32;
}
.button1:hover {
	background-color: #bc2710;
}
.button1:active {
	background-color: #bc2710;
	box-shadow: 0 5px #666;
	transform: translateY(4px);
}	

.button2{
	background-color: #ED4C32;
}
.button2:hover {
	background-color: #bc2710;
}
.button2:active {
	background-color: #bc2710;
	box-shadow: 0 5px #666;
	transform: translateY(4px);
}	
</style>
```

# Afterword #
Those configuration mentioned above work together when the report is shown via the Sharperlight service.
Clicking the "Select All" button will tick all the checkboxes displayed on the page, and clicking "Deselect All" will untick all the checkboxes.

Although this is a simple code, we can further extend the standard web report that Sharperlight creates by using JavaScript, such as sending only the selected items to the next process. Sharperlight provides various endpoints in the Sharperlight RESTful service, so it seems that we can develop web applications quickly.