Loading custom HTML and bootstrap within a Suitelet Form
I want to share this nice hack I created to allow to run custom HTML within a Netsuite form. I am using it to load bootstrap and sweet alert, but it can be used for a lot more! In this example I am loading a basic bootstrap template, it can be tweaked to send POST messages to the suitelet and load more jQuery plugins and scripts.
The end result:
Note: This is a hack, so beware.
Leave a comment if you liked it or think it can be improved!
Suitescript 2.x version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
/* * Suitelet hack to load a custom html page within a Netsuite Form. Created by Adolfo Garza (borncorp) */ var ENCODEMODULE, RUNTIMEMODULE, UIMODULE, URLMODULE, DEPLOYMENT_URL; //I like loading my modules as globals so I can access them whenever I want /** *@NApiVersion 2.x *@NScriptType Suitelet *@NModuleScope Public */ define(["N/encode", "N/runtime", 'N/ui/serverWidget', 'N/url'], runSuitelet); //********************** MAIN FUNCTION ********************** function runSuitelet(encode, runtime, ui, url){ ENCODEMODULE= encode; RUNTIMEMODULE= runtime; UIMODULE = ui; URLMODULE = url; var returnObj = {}; returnObj.onRequest = execute; return returnObj; } function execute(context){ DEPLOYMENT_URL = getDeploymentURL(); try { if (context.request.method == 'GET') { var form = getInjectableForm(); context.response.writePage(form); return; } return; } catch (e) { log.error("ERROR", e.toString()); context.response.write(e.toString()); } return; } function getInjectableForm(){ //*********** Create Form *********** var form = UIMODULE.createForm({ title: ' ' }); var bodyAreaField = form.addField({ id : 'custpage_bodyareafield', type : UIMODULE.FieldType.INLINEHTML, label : 'Body Area Field' }); //*********** Prepare HTML and scripts to Inject *********** var body = getBody(); clientCode = clientCode.replace('$PAGEBODY$', body).replace('$DEPLOYMENT_URL$', DEPLOYMENT_URL); var base64ClientCode = toBase64(clientCode); var scriptToInject = 'console.log(\'Added bottom script element\');'; scriptToInject += "eval( atob(\'" + base64ClientCode + "\') );"; //*********** Injecting HTML and scripts into an the Body Area Field *********** bodyAreaField.defaultValue = '<script>var script = document.createElement(\'script\');script.setAttribute(\'type\', \'text/javascript\');script.appendChild(document.createTextNode(\"' + scriptToInject + '\" ));document.body.appendChild(script);</script>'; return form; } /** * Gets HTML that will be injected into the Suitelet. Use an HTML minifier tool to achieve this one string output. * @returns {string} HTML String */ function getBody(){ return "<div style='width:100%' class='container-fluid'> " + //Replace with your HTML " <div class='container theme-showcase' role='main'> <div class='jumbotron'> <h1>Theme example</h1> <p>This is a template showcasing the optional theme stylesheet included in Bootstrap. Use it as a starting point to create something more unique by building on or modifying it.</p></div><div class='page-header'> <h1>Buttons</h1> </div><p> <button type='button' class='btn btn-lg btn-default'>Default</button> <button type='button' class='btn btn-lg btn-primary'>Primary</button> <button type='button' class='btn btn-lg btn-success'>Success</button> <button type='button' class='btn btn-lg btn-info'>Info</button> <button type='button' class='btn btn-lg btn-warning'>Warning</button> <button type='button' class='btn btn-lg btn-danger'>Danger</button> <button type='button' class='btn btn-lg btn-link'>Link</button> </p><p> <button type='button' class='btn btn-default'>Default</button> <button type='button' class='btn btn-primary'>Primary</button> <button type='button' class='btn btn-success'>Success</button> <button type='button' class='btn btn-info'>Info</button> <button type='button' class='btn btn-warning'>Warning</button> <button type='button' class='btn btn-danger'>Danger</button> <button type='button' class='btn btn-link'>Link</button> </p><p> <button type='button' class='btn btn-sm btn-default'>Default</button> <button type='button' class='btn btn-sm btn-primary'>Primary</button> <button type='button' class='btn btn-sm btn-success'>Success</button> <button type='button' class='btn btn-sm btn-info'>Info</button> <button type='button' class='btn btn-sm btn-warning'>Warning</button> <button type='button' class='btn btn-sm btn-danger'>Danger</button> <button type='button' class='btn btn-sm btn-link'>Link</button> </p><p> <button type='button' class='btn btn-xs btn-default'>Default</button> <button type='button' class='btn btn-xs btn-primary'>Primary</button> <button type='button' class='btn btn-xs btn-success'>Success</button> <button type='button' class='btn btn-xs btn-info'>Info</button> <button type='button' class='btn btn-xs btn-warning'>Warning</button> <button type='button' class='btn btn-xs btn-danger'>Danger</button> <button type='button' class='btn btn-xs btn-link'>Link</button> </p><div class='page-header'> <h1>Tables</h1> </div><div class='row'> <div class='col-md-6'> <table class='table'> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr></thead> <tbody> <tr> <td>1</td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr> <td>2</td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr> <td>3</td><td>Larry</td><td>the Bird</td><td>@twitter</td></tr></tbody> </table> </div><div class='col-md-6'> <table class='table table-striped'> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr></thead> <tbody> <tr> <td>1</td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr> <td>2</td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr> <td>3</td><td>Larry</td><td>the Bird</td><td>@twitter</td></tr></tbody> </table> </div></div><div class='row'> <div class='col-md-6'> <table class='table table-bordered'> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr></thead> <tbody> <tr> <td rowspan='2'>1</td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr> <td>Mark</td><td>Otto</td><td>@TwBootstrap</td></tr><tr> <td>2</td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr> <td>3</td><td colspan='2'>Larry the Bird</td><td>@twitter</td></tr></tbody> </table> </div><div class='col-md-6'> <table class='table table-condensed'> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr></thead> <tbody> <tr> <td>1</td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr> <td>2</td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr> <td>3</td><td colspan='2'>Larry the Bird</td><td>@twitter</td></tr></tbody> </table> </div></div><div class='page-header'> <h1>Thumbnails</h1> </div><img data-src='holder.js/200x200' class='img-thumbnail' alt='A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera'> <div class='page-header'> <h1>Labels</h1> </div><h1> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h1> <h2> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h2> <h3> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h3> <h4> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h4> <h5> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h5> <h6> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h6> <p> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </p><div class='page-header'> <h1>Badges</h1> </div><p> <a href='#'>Inbox <span class='badge'>42</span></a> </p><ul class='nav nav-pills' role='tablist'> <li role='presentation' class='active'><a href='#'>Home <span class='badge'>42</span></a></li><li role='presentation'><a href='#'>Profile</a></li><li role='presentation'><a href='#'>Messages <span class='badge'>3</span></a></li></ul> <div class='page-header'> <h1>Dropdown menus</h1> </div><div class='dropdown theme-dropdown clearfix'> <a id='dropdownMenu1' href='#' class='sr-only dropdown-toggle' data-toggle='dropdown' role='button' aria-haspopup='true' aria-expanded='false'>Dropdown <span class='caret'></span></a> <ul class='dropdown-menu' aria-labelledby='dropdownMenu1'> <li class='active'><a href='#'>Action</a></li><li><a href='#'>Another action</a></li><li><a href='#'>Something else here</a></li><li role='separator' class='divider'></li><li><a href='#'>Separated link</a></li></ul> </div><div class='page-header'> <h1>Navs</h1> </div><ul class='nav nav-tabs' role='tablist'> <li role='presentation' class='active'><a href='#'>Home</a></li><li role='presentation'><a href='#'>Profile</a></li><li role='presentation'><a href='#'>Messages</a></li></ul> <ul class='nav nav-pills' role='tablist'> <li role='presentation' class='active'><a href='#'>Home</a></li><li role='presentation'><a href='#'>Profile</a></li><li role='presentation'><a href='#'>Messages</a></li></ul> <div class='page-header'> <h1>Navbars</h1> </div><nav class='navbar navbar-default'> <div class='container'> <div class='navbar-header'> <button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='.navbar-collapse'> <span class='sr-only'>Toggle navigation</span> <span class='icon-bar'></span> <span class='icon-bar'></span> <span class='icon-bar'></span> </button> <a class='navbar-brand' href='#'>Project name</a> </div><div class='navbar-collapse collapse'> <ul class='nav navbar-nav'> <li class='active'><a href='#'>Home</a></li><li><a href='#about'>About</a></li><li><a href='#contact'>Contact</a></li><li class='dropdown'> <a href='#' class='dropdown-toggle' data-toggle='dropdown' role='button' aria-haspopup='true' aria-expanded='false'>Dropdown <span class='caret'></span></a> <ul class='dropdown-menu'> <li><a href='#'>Action</a></li><li><a href='#'>Another action</a></li><li><a href='#'>Something else here</a></li><li role='separator' class='divider'></li><li class='dropdown-header'>Nav header</li><li><a href='#'>Separated link</a></li><li><a href='#'>One more separated link</a></li></ul> </li></ul> </div></div></nav> <nav class='navbar navbar-inverse'> <div class='container'> <div class='navbar-header'> <button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='.navbar-collapse'> <span class='sr-only'>Toggle navigation</span> <span class='icon-bar'></span> <span class='icon-bar'></span> <span class='icon-bar'></span> </button> <a class='navbar-brand' href='#'>Project name</a> </div><div class='navbar-collapse collapse'> <ul class='nav navbar-nav'> <li class='active'><a href='#'>Home</a></li><li><a href='#about'>About</a></li><li><a href='#contact'>Contact</a></li><li class='dropdown'> <a href='#' class='dropdown-toggle' data-toggle='dropdown' role='button' aria-haspopup='true' aria-expanded='false'>Dropdown <span class='caret'></span></a> <ul class='dropdown-menu'> <li><a href='#'>Action</a></li><li><a href='#'>Another action</a></li><li><a href='#'>Something else here</a></li><li role='separator' class='divider'></li><li class='dropdown-header'>Nav header</li><li><a href='#'>Separated link</a></li><li><a href='#'>One more separated link</a></li></ul> </li></ul> </div></div></nav> <div class='page-header'> <h1>Alerts</h1> </div><div class='alert alert-success' role='alert'> <strong>Well done!</strong> You successfully read this important alert message. </div><div class='alert alert-info' role='alert'> <strong>Heads up!</strong> This alert needs your attention, but it's not super important. </div><div class='alert alert-warning' role='alert'> <strong>Warning!</strong> Best check yo self, you're not looking too good. </div><div class='alert alert-danger' role='alert'> <strong>Oh snap!</strong> Change a few things up and try submitting again. </div><div class='page-header'> <h1>Progress bars</h1> </div><div class='progress'> <div class='progress-bar' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 60%;'><span class='sr-only'>60% Complete</span></div></div><div class='progress'> <div class='progress-bar progress-bar-success' role='progressbar' aria-valuenow='40' aria-valuemin='0' aria-valuemax='100' style='width: 40%'><span class='sr-only'>40% Complete (success)</span></div></div><div class='progress'> <div class='progress-bar progress-bar-info' role='progressbar' aria-valuenow='20' aria-valuemin='0' aria-valuemax='100' style='width: 20%'><span class='sr-only'>20% Complete</span></div></div><div class='progress'> <div class='progress-bar progress-bar-warning' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 60%'><span class='sr-only'>60% Complete (warning)</span></div></div><div class='progress'> <div class='progress-bar progress-bar-danger' role='progressbar' aria-valuenow='80' aria-valuemin='0' aria-valuemax='100' style='width: 80%'><span class='sr-only'>80% Complete (danger)</span></div></div><div class='progress'> <div class='progress-bar progress-bar-striped' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 60%'><span class='sr-only'>60% Complete</span></div></div><div class='progress'> <div class='progress-bar progress-bar-success' style='width: 35%'><span class='sr-only'>35% Complete (success)</span></div><div class='progress-bar progress-bar-warning' style='width: 20%'><span class='sr-only'>20% Complete (warning)</span></div><div class='progress-bar progress-bar-danger' style='width: 10%'><span class='sr-only'>10% Complete (danger)</span></div></div><div class='page-header'> <h1>List groups</h1> </div><div class='row'> <div class='col-sm-4'> <ul class='list-group'> <li class='list-group-item'>Cras justo odio</li><li class='list-group-item'>Dapibus ac facilisis in</li><li class='list-group-item'>Morbi leo risus</li><li class='list-group-item'>Porta ac consectetur ac</li><li class='list-group-item'>Vestibulum at eros</li></ul> </div><div class='col-sm-4'> <div class='list-group'> <a href='#' class='list-group-item active'> Cras justo odio </a> <a href='#' class='list-group-item'>Dapibus ac facilisis in</a> <a href='#' class='list-group-item'>Morbi leo risus</a> <a href='#' class='list-group-item'>Porta ac consectetur ac</a> <a href='#' class='list-group-item'>Vestibulum at eros</a> </div></div><div class='col-sm-4'> <div class='list-group'> <a href='#' class='list-group-item active'> <h4 class='list-group-item-heading'>List group item heading</h4> <p class='list-group-item-text'>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p></a> <a href='#' class='list-group-item'> <h4 class='list-group-item-heading'>List group item heading</h4> <p class='list-group-item-text'>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p></a> <a href='#' class='list-group-item'> <h4 class='list-group-item-heading'>List group item heading</h4> <p class='list-group-item-text'>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p></a> </div></div></div><div class='page-header'> <h1>Panels</h1> </div><div class='row'> <div class='col-sm-4'> <div class='panel panel-default'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div><div class='panel panel-primary'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div></div><div class='col-sm-4'> <div class='panel panel-success'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div><div class='panel panel-info'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div></div><div class='col-sm-4'> <div class='panel panel-warning'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div><div class='panel panel-danger'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div></div></div><div class='page-header'> <h1>Wells</h1> </div><div class='well'> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed diam eget risus varius blandit sit amet non magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Aenean lacinia bibendum nulla sed consectetur.</p></div><div class='page-header'> <h1>Carousel</h1> </div><div id='carousel-example-generic' class='carousel slide' data-ride='carousel'> <ol class='carousel-indicators'> <li data-target='#carousel-example-generic' data-slide-to='0' class='active'></li><li data-target='#carousel-example-generic' data-slide-to='1'></li><li data-target='#carousel-example-generic' data-slide-to='2'></li></ol> <div class='carousel-inner' role='listbox'> <div class='item active'> <img data-src='holder.js/1140x500/auto/#777:#555/text:First slide' alt='First slide'> </div><div class='item'> <img data-src='holder.js/1140x500/auto/#666:#444/text:Second slide' alt='Second slide'> </div><div class='item'> <img data-src='holder.js/1140x500/auto/#555:#333/text:Third slide' alt='Third slide'> </div></div><a class='left carousel-control' href='#carousel-example-generic' role='button' data-slide='prev'> <span class='glyphicon glyphicon-chevron-left' aria-hidden='true'></span> <span class='sr-only'>Previous</span> </a> <a class='right carousel-control' href='#carousel-example-generic' role='button' data-slide='next'> <span class='glyphicon glyphicon-chevron-right' aria-hidden='true'></span> <span class='sr-only'>Next</span> </a> </div></div>" + "</div>"; } var clientCode = 'run(); ' + function run() { console.log('Running client code'); //*********** GLOBAL VARIABLES *********** $ = jQuery; DEPLOYMENT_URL = '$DEPLOYMENT_URL$'; THISURL = $(location).attr('href'); //*********** After DOM loads run this: *********** $(function() { injectHeaderScripts(); //Loads Libraries that will be placed on header (Optional) $(window).bind('load', injectHTML); //Replaces Suitelet's body with custom HTML once the window has fully loaded(Required) waitForLibraries(['swal'], runCustomFunctions); //Runs additional logic after required libraries have loaded (Optional) }); return; //*********** HELPER FUNCTIONS *********** /** * Loads Libraries that will be placed on header (Optional) */ function injectHeaderScripts(){ console.log('loadHeaderLibraries START'); loadjscssfile( "https://code.jquery.com/jquery-1.11.3.min.js" ); loadjscssfile( "https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.0/sweetalert.min.js"); loadjscssfile("https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.0/sweetalert.min.css"); loadjscssfile("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"); loadjscssfile("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"); loadjscssfile( "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" ); console.log('loadHeaderLibraries END'); //*********** HELPER FUNCTION *********** function loadjscssfile(filename) { var filetype = filename.substr(filename.lastIndexOf('.') + 1).toLowerCase(); if (filetype == "js") { //if filename is a external JavaScript file var fileref = document.createElement('script') fileref.setAttribute("type", "text/javascript") fileref.setAttribute("src", filename) } else if (filetype == "css") { //if filename is an external CSS file var fileref = document.createElement("link") fileref.setAttribute("rel", "stylesheet") fileref.setAttribute("type", "text/css") fileref.setAttribute("href", filename) } if (typeof fileref != "undefined"){ document.getElementsByTagName("head")[0].appendChild(fileref) } console.log(filename + ' plugin loaded'); } } function runCustomFunctions() { console.log('clientFunctions START'); var DEPLOYMENT_URL = '$DEPLOYMENT_URL$'; swal('Good job ' + nlapiGetContext().name.split(' ').shift(), 'This code is loaded in the footer. Thanks for trying my script!', "success"); } function waitForLibraries(libraries, functionToRun){ var loadedLibraries = 0; for (var i in libraries) { var library = libraries[i]; if(eval('typeof ' + library)!='undefined'){ loadedLibraries++; } } window.setTimeout(function(){ if(loadedLibraries != libraries.length){ waitForLibraries(libraries, functionToRun); } else{ console.log(library + ' loaded'); functionToRun(); } },500); } function injectHTML(){ var html = ' $PAGEBODY$ '; //This string will be replaced by the Suitelet jQuery("#main_form")[0].outerHTML = html; } } /** * Gets deployment URL. Useful for sending POST requests to this same suitelet. * @returns {string} Deployment URL */ function getDeploymentURL(){ return URLMODULE.resolveScript({ scriptId: RUNTIMEMODULE.getCurrentScript().id, deploymentId: RUNTIMEMODULE.getCurrentScript().deploymentId, returnExternalUrl: false, }); } function toBase64(stringInput){ return ENCODEMODULE.convert({ string: stringInput, inputEncoding: ENCODEMODULE.Encoding.UTF_8, outputEncoding: ENCODEMODULE.Encoding.BASE_64 }); } |
Suitescript 2.1 version
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
/* * Suitelet hack to load a custom html page within a Netsuite Form. Created by Adolfo Garza (borncorp) */ var ENCODEMODULE, RUNTIMEMODULE, UIMODULE, URLMODULE, DEPLOYMENT_URL; //I like loading my modules as globals so I can access them whenever I want /** *@NApiVersion 2.1 *@NScriptType Suitelet *@NModuleScope Public */ define(["N/encode", "N/runtime", 'N/ui/serverWidget', 'N/url'], runSuitelet); //********************** MAIN FUNCTION ********************** function runSuitelet(encode, runtime, ui, url){ ENCODEMODULE= encode; RUNTIMEMODULE= runtime; UIMODULE = ui; URLMODULE = url; var returnObj = {}; returnObj.onRequest = execute; return returnObj; } function execute(context){ DEPLOYMENT_URL = getDeploymentURL(); try { if (context.request.method == 'GET') { var form = getInjectableForm(); context.response.writePage(form); return; } return; } catch (e) { log.error("ERROR", e.toString()); context.response.write(e.toString()); } return; } function getInjectableForm(){ //*********** Create Form *********** var form = UIMODULE.createForm({ title: ' ' }); var bodyAreaField = form.addField({ id : 'custpage_bodyareafield', type : UIMODULE.FieldType.INLINEHTML, label : 'Body Area Field' }); //*********** Prepare HTML and scripts to Inject *********** var body = getBody(); clientCode = clientCode.replace('$PAGEBODY$', body).replace('$DEPLOYMENT_URL$', DEPLOYMENT_URL); var base64ClientCode = toBase64(clientCode); var scriptToInject = 'console.log(\'Added bottom script element\');'; scriptToInject += "eval( atob(\'" + base64ClientCode + "\') );"; //*********** Injecting HTML and scripts into an the Body Area Field *********** bodyAreaField.defaultValue = '<script>var script = document.createElement(\'script\');script.setAttribute(\'type\', \'text/javascript\');script.appendChild(document.createTextNode(\"' + scriptToInject + '\" ));document.body.appendChild(script);</script>'; return form; } /** * Gets HTML that will be injected into the Suitelet. Use an HTML minifier tool to achieve this one string output. * @returns {string} HTML String */ function getBody(){ return "<div style='width:100%' class='container-fluid'> " + //Replace with your HTML " <div class='container theme-showcase' role='main'> <div class='jumbotron'> <h1>Theme example</h1> <p>This is a template showcasing the optional theme stylesheet included in Bootstrap. Use it as a starting point to create something more unique by building on or modifying it.</p></div><div class='page-header'> <h1>Buttons</h1> </div><p> <button type='button' class='btn btn-lg btn-default'>Default</button> <button type='button' class='btn btn-lg btn-primary'>Primary</button> <button type='button' class='btn btn-lg btn-success'>Success</button> <button type='button' class='btn btn-lg btn-info'>Info</button> <button type='button' class='btn btn-lg btn-warning'>Warning</button> <button type='button' class='btn btn-lg btn-danger'>Danger</button> <button type='button' class='btn btn-lg btn-link'>Link</button> </p><p> <button type='button' class='btn btn-default'>Default</button> <button type='button' class='btn btn-primary'>Primary</button> <button type='button' class='btn btn-success'>Success</button> <button type='button' class='btn btn-info'>Info</button> <button type='button' class='btn btn-warning'>Warning</button> <button type='button' class='btn btn-danger'>Danger</button> <button type='button' class='btn btn-link'>Link</button> </p><p> <button type='button' class='btn btn-sm btn-default'>Default</button> <button type='button' class='btn btn-sm btn-primary'>Primary</button> <button type='button' class='btn btn-sm btn-success'>Success</button> <button type='button' class='btn btn-sm btn-info'>Info</button> <button type='button' class='btn btn-sm btn-warning'>Warning</button> <button type='button' class='btn btn-sm btn-danger'>Danger</button> <button type='button' class='btn btn-sm btn-link'>Link</button> </p><p> <button type='button' class='btn btn-xs btn-default'>Default</button> <button type='button' class='btn btn-xs btn-primary'>Primary</button> <button type='button' class='btn btn-xs btn-success'>Success</button> <button type='button' class='btn btn-xs btn-info'>Info</button> <button type='button' class='btn btn-xs btn-warning'>Warning</button> <button type='button' class='btn btn-xs btn-danger'>Danger</button> <button type='button' class='btn btn-xs btn-link'>Link</button> </p><div class='page-header'> <h1>Tables</h1> </div><div class='row'> <div class='col-md-6'> <table class='table'> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr></thead> <tbody> <tr> <td>1</td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr> <td>2</td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr> <td>3</td><td>Larry</td><td>the Bird</td><td>@twitter</td></tr></tbody> </table> </div><div class='col-md-6'> <table class='table table-striped'> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr></thead> <tbody> <tr> <td>1</td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr> <td>2</td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr> <td>3</td><td>Larry</td><td>the Bird</td><td>@twitter</td></tr></tbody> </table> </div></div><div class='row'> <div class='col-md-6'> <table class='table table-bordered'> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr></thead> <tbody> <tr> <td rowspan='2'>1</td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr> <td>Mark</td><td>Otto</td><td>@TwBootstrap</td></tr><tr> <td>2</td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr> <td>3</td><td colspan='2'>Larry the Bird</td><td>@twitter</td></tr></tbody> </table> </div><div class='col-md-6'> <table class='table table-condensed'> <thead> <tr> <th>#</th> <th>First Name</th> <th>Last Name</th> <th>Username</th> </tr></thead> <tbody> <tr> <td>1</td><td>Mark</td><td>Otto</td><td>@mdo</td></tr><tr> <td>2</td><td>Jacob</td><td>Thornton</td><td>@fat</td></tr><tr> <td>3</td><td colspan='2'>Larry the Bird</td><td>@twitter</td></tr></tbody> </table> </div></div><div class='page-header'> <h1>Thumbnails</h1> </div><img data-src='holder.js/200x200' class='img-thumbnail' alt='A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera'> <div class='page-header'> <h1>Labels</h1> </div><h1> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h1> <h2> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h2> <h3> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h3> <h4> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h4> <h5> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h5> <h6> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </h6> <p> <span class='label label-default'>Default</span> <span class='label label-primary'>Primary</span> <span class='label label-success'>Success</span> <span class='label label-info'>Info</span> <span class='label label-warning'>Warning</span> <span class='label label-danger'>Danger</span> </p><div class='page-header'> <h1>Badges</h1> </div><p> <a href='#'>Inbox <span class='badge'>42</span></a> </p><ul class='nav nav-pills' role='tablist'> <li role='presentation' class='active'><a href='#'>Home <span class='badge'>42</span></a></li><li role='presentation'><a href='#'>Profile</a></li><li role='presentation'><a href='#'>Messages <span class='badge'>3</span></a></li></ul> <div class='page-header'> <h1>Dropdown menus</h1> </div><div class='dropdown theme-dropdown clearfix'> <a id='dropdownMenu1' href='#' class='sr-only dropdown-toggle' data-toggle='dropdown' role='button' aria-haspopup='true' aria-expanded='false'>Dropdown <span class='caret'></span></a> <ul class='dropdown-menu' aria-labelledby='dropdownMenu1'> <li class='active'><a href='#'>Action</a></li><li><a href='#'>Another action</a></li><li><a href='#'>Something else here</a></li><li role='separator' class='divider'></li><li><a href='#'>Separated link</a></li></ul> </div><div class='page-header'> <h1>Navs</h1> </div><ul class='nav nav-tabs' role='tablist'> <li role='presentation' class='active'><a href='#'>Home</a></li><li role='presentation'><a href='#'>Profile</a></li><li role='presentation'><a href='#'>Messages</a></li></ul> <ul class='nav nav-pills' role='tablist'> <li role='presentation' class='active'><a href='#'>Home</a></li><li role='presentation'><a href='#'>Profile</a></li><li role='presentation'><a href='#'>Messages</a></li></ul> <div class='page-header'> <h1>Navbars</h1> </div><nav class='navbar navbar-default'> <div class='container'> <div class='navbar-header'> <button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='.navbar-collapse'> <span class='sr-only'>Toggle navigation</span> <span class='icon-bar'></span> <span class='icon-bar'></span> <span class='icon-bar'></span> </button> <a class='navbar-brand' href='#'>Project name</a> </div><div class='navbar-collapse collapse'> <ul class='nav navbar-nav'> <li class='active'><a href='#'>Home</a></li><li><a href='#about'>About</a></li><li><a href='#contact'>Contact</a></li><li class='dropdown'> <a href='#' class='dropdown-toggle' data-toggle='dropdown' role='button' aria-haspopup='true' aria-expanded='false'>Dropdown <span class='caret'></span></a> <ul class='dropdown-menu'> <li><a href='#'>Action</a></li><li><a href='#'>Another action</a></li><li><a href='#'>Something else here</a></li><li role='separator' class='divider'></li><li class='dropdown-header'>Nav header</li><li><a href='#'>Separated link</a></li><li><a href='#'>One more separated link</a></li></ul> </li></ul> </div></div></nav> <nav class='navbar navbar-inverse'> <div class='container'> <div class='navbar-header'> <button type='button' class='navbar-toggle collapsed' data-toggle='collapse' data-target='.navbar-collapse'> <span class='sr-only'>Toggle navigation</span> <span class='icon-bar'></span> <span class='icon-bar'></span> <span class='icon-bar'></span> </button> <a class='navbar-brand' href='#'>Project name</a> </div><div class='navbar-collapse collapse'> <ul class='nav navbar-nav'> <li class='active'><a href='#'>Home</a></li><li><a href='#about'>About</a></li><li><a href='#contact'>Contact</a></li><li class='dropdown'> <a href='#' class='dropdown-toggle' data-toggle='dropdown' role='button' aria-haspopup='true' aria-expanded='false'>Dropdown <span class='caret'></span></a> <ul class='dropdown-menu'> <li><a href='#'>Action</a></li><li><a href='#'>Another action</a></li><li><a href='#'>Something else here</a></li><li role='separator' class='divider'></li><li class='dropdown-header'>Nav header</li><li><a href='#'>Separated link</a></li><li><a href='#'>One more separated link</a></li></ul> </li></ul> </div></div></nav> <div class='page-header'> <h1>Alerts</h1> </div><div class='alert alert-success' role='alert'> <strong>Well done!</strong> You successfully read this important alert message. </div><div class='alert alert-info' role='alert'> <strong>Heads up!</strong> This alert needs your attention, but it's not super important. </div><div class='alert alert-warning' role='alert'> <strong>Warning!</strong> Best check yo self, you're not looking too good. </div><div class='alert alert-danger' role='alert'> <strong>Oh snap!</strong> Change a few things up and try submitting again. </div><div class='page-header'> <h1>Progress bars</h1> </div><div class='progress'> <div class='progress-bar' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 60%;'><span class='sr-only'>60% Complete</span></div></div><div class='progress'> <div class='progress-bar progress-bar-success' role='progressbar' aria-valuenow='40' aria-valuemin='0' aria-valuemax='100' style='width: 40%'><span class='sr-only'>40% Complete (success)</span></div></div><div class='progress'> <div class='progress-bar progress-bar-info' role='progressbar' aria-valuenow='20' aria-valuemin='0' aria-valuemax='100' style='width: 20%'><span class='sr-only'>20% Complete</span></div></div><div class='progress'> <div class='progress-bar progress-bar-warning' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 60%'><span class='sr-only'>60% Complete (warning)</span></div></div><div class='progress'> <div class='progress-bar progress-bar-danger' role='progressbar' aria-valuenow='80' aria-valuemin='0' aria-valuemax='100' style='width: 80%'><span class='sr-only'>80% Complete (danger)</span></div></div><div class='progress'> <div class='progress-bar progress-bar-striped' role='progressbar' aria-valuenow='60' aria-valuemin='0' aria-valuemax='100' style='width: 60%'><span class='sr-only'>60% Complete</span></div></div><div class='progress'> <div class='progress-bar progress-bar-success' style='width: 35%'><span class='sr-only'>35% Complete (success)</span></div><div class='progress-bar progress-bar-warning' style='width: 20%'><span class='sr-only'>20% Complete (warning)</span></div><div class='progress-bar progress-bar-danger' style='width: 10%'><span class='sr-only'>10% Complete (danger)</span></div></div><div class='page-header'> <h1>List groups</h1> </div><div class='row'> <div class='col-sm-4'> <ul class='list-group'> <li class='list-group-item'>Cras justo odio</li><li class='list-group-item'>Dapibus ac facilisis in</li><li class='list-group-item'>Morbi leo risus</li><li class='list-group-item'>Porta ac consectetur ac</li><li class='list-group-item'>Vestibulum at eros</li></ul> </div><div class='col-sm-4'> <div class='list-group'> <a href='#' class='list-group-item active'> Cras justo odio </a> <a href='#' class='list-group-item'>Dapibus ac facilisis in</a> <a href='#' class='list-group-item'>Morbi leo risus</a> <a href='#' class='list-group-item'>Porta ac consectetur ac</a> <a href='#' class='list-group-item'>Vestibulum at eros</a> </div></div><div class='col-sm-4'> <div class='list-group'> <a href='#' class='list-group-item active'> <h4 class='list-group-item-heading'>List group item heading</h4> <p class='list-group-item-text'>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p></a> <a href='#' class='list-group-item'> <h4 class='list-group-item-heading'>List group item heading</h4> <p class='list-group-item-text'>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p></a> <a href='#' class='list-group-item'> <h4 class='list-group-item-heading'>List group item heading</h4> <p class='list-group-item-text'>Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p></a> </div></div></div><div class='page-header'> <h1>Panels</h1> </div><div class='row'> <div class='col-sm-4'> <div class='panel panel-default'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div><div class='panel panel-primary'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div></div><div class='col-sm-4'> <div class='panel panel-success'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div><div class='panel panel-info'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div></div><div class='col-sm-4'> <div class='panel panel-warning'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div><div class='panel panel-danger'> <div class='panel-heading'> <h3 class='panel-title'>Panel title</h3> </div><div class='panel-body'> Panel content </div></div></div></div><div class='page-header'> <h1>Wells</h1> </div><div class='well'> <p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed diam eget risus varius blandit sit amet non magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Aenean lacinia bibendum nulla sed consectetur.</p></div><div class='page-header'> <h1>Carousel</h1> </div><div id='carousel-example-generic' class='carousel slide' data-ride='carousel'> <ol class='carousel-indicators'> <li data-target='#carousel-example-generic' data-slide-to='0' class='active'></li><li data-target='#carousel-example-generic' data-slide-to='1'></li><li data-target='#carousel-example-generic' data-slide-to='2'></li></ol> <div class='carousel-inner' role='listbox'> <div class='item active'> <img data-src='holder.js/1140x500/auto/#777:#555/text:First slide' alt='First slide'> </div><div class='item'> <img data-src='holder.js/1140x500/auto/#666:#444/text:Second slide' alt='Second slide'> </div><div class='item'> <img data-src='holder.js/1140x500/auto/#555:#333/text:Third slide' alt='Third slide'> </div></div><a class='left carousel-control' href='#carousel-example-generic' role='button' data-slide='prev'> <span class='glyphicon glyphicon-chevron-left' aria-hidden='true'></span> <span class='sr-only'>Previous</span> </a> <a class='right carousel-control' href='#carousel-example-generic' role='button' data-slide='next'> <span class='glyphicon glyphicon-chevron-right' aria-hidden='true'></span> <span class='sr-only'>Next</span> </a> </div></div>" + "</div>"; } var clientCode = 'run(); ' + function run() { console.log('Running client code'); //*********** GLOBAL VARIABLES *********** $ = jQuery; DEPLOYMENT_URL = '$DEPLOYMENT_URL$'; THISURL = $(location).attr('href'); //*********** After DOM loads run this: *********** $(function() { injectHeaderScripts(); //Loads Libraries that will be placed on header (Optional) $(window).bind('load', injectHTML); //Replaces Suitelet's body with custom HTML once the window has fully loaded(Required) waitForLibraries(['swal'], runCustomFunctions); //Runs additional logic after required libraries have loaded (Optional) }); return; //*********** HELPER FUNCTIONS *********** /** * Loads Libraries that will be placed on header (Optional) */ function injectHeaderScripts(){ console.log('loadHeaderLibraries START'); loadjscssfile( "https://code.jquery.com/jquery-1.11.3.min.js" ); loadjscssfile( "https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.0/sweetalert.min.js"); loadjscssfile("https://cdnjs.cloudflare.com/ajax/libs/sweetalert/1.1.0/sweetalert.min.css"); loadjscssfile("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"); loadjscssfile("https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap-theme.min.css"); loadjscssfile( "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js" ); console.log('loadHeaderLibraries END'); //*********** HELPER FUNCTION *********** function loadjscssfile(filename) { var filetype = filename.substr(filename.lastIndexOf('.') + 1).toLowerCase(); if (filetype == "js") { //if filename is a external JavaScript file var fileref = document.createElement('script') fileref.setAttribute("type", "text/javascript") fileref.setAttribute("src", filename) } else if (filetype == "css") { //if filename is an external CSS file var fileref = document.createElement("link") fileref.setAttribute("rel", "stylesheet") fileref.setAttribute("type", "text/css") fileref.setAttribute("href", filename) } if (typeof fileref != "undefined"){ document.getElementsByTagName("head")[0].appendChild(fileref) } console.log(filename + ' plugin loaded'); } } function runCustomFunctions() { console.log('clientFunctions START'); var DEPLOYMENT_URL = '$DEPLOYMENT_URL$'; swal('Good job ' + nlapiGetContext().name.split(' ').shift(), 'This code is loaded in the footer. Thanks for trying my script!', "success"); } function waitForLibraries(libraries, functionToRun){ var loadedLibraries = 0; for (var i in libraries) { var library = libraries[i]; if(eval('typeof ' + library)!='undefined'){ loadedLibraries++; } } window.setTimeout(function(){ if(loadedLibraries != libraries.length){ waitForLibraries(libraries, functionToRun); } else{ console.log(library + ' loaded'); functionToRun(); } },500); } function injectHTML(){ var html = `$PAGEBODY$`; //This string will be replaced by the Suitelet jQuery("#main_form")[0].outerHTML = html; } } /** * Gets deployment URL. Useful for sending POST requests to this same suitelet. * @returns {string} Deployment URL */ function getDeploymentURL(){ return URLMODULE.resolveScript({ scriptId: RUNTIMEMODULE.getCurrentScript().id, deploymentId: RUNTIMEMODULE.getCurrentScript().deploymentId, returnExternalUrl: false, }); } function toBase64(stringInput){ return ENCODEMODULE.convert({ string: stringInput, inputEncoding: ENCODEMODULE.Encoding.UTF_8, outputEncoding: ENCODEMODULE.Encoding.BASE_64 }); } |