Troy Lea's presentation on JavaScript and jQuery - Nagios XI Tips, Tricks and How-To.
The presentation was given during the Nagios World Conference North America held Oct 13th - Oct 16th, 2014 in Saint Paul, MN. For more information on the conference (including photos and videos), visit: http://go.nagios.com/conference
Powerful Google developer tools for immediate impact! (2023-24 C)
Nagios Conference 2014 - Troy Lea - JavaScript and jQuery - Nagios XI Tips, Tricks and How-To
1. JavaScript and jQuery
Nagios XI Tips, Tricks
and How-To
Troy Lea aka Box293
tlea@nagios.com
Twitter: @box293
2. Introduction & Agenda
• JavaScript and jQuery … it's the #1 cause of
baldness!
• This presentation explains JavaScript and
jQuery
3. What is JavaScript?
• It allows you to change the content of the end
users web page
• Called the “client side”
• Can be performed as an action based on a
users selection or particular mouse click
• No need to reload the entire page
9. JavaScript Alert – Part 2
index.html
<!doctype html>
<html>
<head>
onclick="say_hello('GDay
Mate')"
onclick="say_hello('GDay
<meta charset="utf8"
/>
Mate')"
<title>Demo</title>
</head>
<body>
Blah blah blah
<br/><br/>
<input type="button" value="Click Me" onclick="say_hello('GDay Mate')">
function <script>
function say_hello(say_input) {
hello(input) {
alert(input);
}
function alert(input);
say_hello(input) {
}
</alert(script>
input);
}
</body>
</html>
10. JavaScript Alert – Part 3
Example 1 = Called a function without any values
onclick="say_hello()"
function say_hello() {
alert('say hello');
}
Example 2 = Called a function sending a value
onclick="say_hello('GDay
Mate')"
function say_hello(input) {
alert(input);
}
17. Separate JavaScript File – Part 2
my_javascript.js
function select_value(input) {
var the_value = $('#' + input).val();
alert(the_value);
}
● Separating the JavaScript/jQuery from the
HTML file
●Makes coding easier
● Code works the same
19. PHP – Time To Get Complicated
● PHP = "PHP: Hypertext Preprocessor"
– It's a recursive backronym!
● Builds HTML code on the fly
● PHP code is between the tags
– <?php
– ?>
21. PHP – Escaping Quotes Part 1
● PHP Variables use quotes for the variable value
– Single ' OR Double “
$test = 'Hello There and some HTML Code <br />';
OR
$test = "Hello There and some HTML Code <br />";
22. PHP – Escaping Quotes Part 2
● Without escaping, PHP thinks the variable is
finished and does not expect the characters
that follow
$test = 'Hey look it's a single quote <br />';
OR
$test = "He said "GDay Mate" <br />";
24. PHP – Escaping Quotes Part 4
my_javascript.js
function select_value(input) {
var the_value = $('#' + input).val();
alert(the_value);
}
● In the separate JavaScript file no escaping is
required
● On the previous slide we needed to escape the
single quotes:
● onclick="select_value('id_select')"
25. PHP – Escaping Quotes Part 5
● Double quotes = PHP variables are expanded,
which allows the content to change
dynamically
$food_item = "pizza";
$output = "My favorite food is
$food_item";
● $output will now contain:
My favorite food is pizza
26. PHP – Escaping Quotes Part 6
● Single quotes = The content between the
single quotes is treated as plain text (literal)
$food_item = 'pizza';
$output = 'My favorite food is
$food_item';
● $output will now contain:
My favorite food is $food_item
$food_item was not not expanded, it was treated
as plain text
27. PHP – Escaping Quotes Part 7
● So then why don't I use double quotes like:
● $output = "HTML content";
● Then we won't have to escape those single
quotes right?
● Lets see …
29. PHP – Escaping Quotes Part 9
● So now you can see that while I didn't need to
escape two single quotes, I needed to escape
eight double quotes!
● It's not right or wrong … there's just different
ways to do the same thing
34. What is AJAX?
• A group of technologies
used to implement
web applications
• Communication with a server in the
background
• Does not interfere with the current state of
the page
35. AJAX Example – Part 1
index.php
<?php
$output = '
<!doctype html>
<html>
<head>
<meta charset="utf8"
/>
<title>Demo</title>
</head>
<body>
Blah blah blah
<br/><br/>
<select id="id_select">
<div id="id_content">
<div id="id_content">
<!<option this
value="one">Strawberry</option>
<option value="two">Grape</will option>
be populated
</select>
<br/><br/>
<input type="button" value="Click Me" onclick="load_content('id_select')">
<br/><br/>
later >
</div>
<div id="id_content">
<!this
will be populated later >
</div>
<script src="jquery2.1.1.
min.js"></script>
<script src="my_javascript.js"></script>
</body>
</html>
';
print $output;
?>
<!this
will be populated
later >
</div>
36. AJAX Example – Part 2
my_javascript.js
function load_content(input) {
var item_selected = $('#' + input).val();
var div_to_load = '#id_content';
$(div_to_load).load('content.php?selection=' + item_selected);
}
content.php
<?php
$selection = $_GET['selection'];
if ($selection == 'one') {
$output = '<img src="foodstrawberry.
png">';
}
elseif ($selection == 'two') {
$output = '<img src="foodgrapes.
png">';
}
print $output;
?>
37. AJAX Example – Part 3
$(div_to_load).load('content.php?selection=' +
item_selected);
● .load() is a jQuery function that performs the
AJAX request
● Server is told to load the page content.php
● “selection” is passed as a variable with the value
of item_selected
● Only the required HTML is generated
● .load() REPLACES the DIV contents
38. Examples - Conclusion
● These examples have demonstrated simple
HTML and JavaScript/jQuery functionality along
with AJAX
● Next I will
demonstrate how to
use these
technologies in Nagios
XI
39. Nagios XI
● Component Demo
● GOAL:
● Show a list of hosts
● Select a host, show a list of services for that
host
● Demo code will be made available with the
presentation after the conference
40. Component Demo - Part 1
Extract from componentdemo.inc.php
case COMPONENT_CONFIGMODE_GETSETTINGSHTML:
$output .= '
Hey there and welcome to the demo!
<br/><br/><br/>
<div id="id_hosts">
<!This
will be populated by the line of script below →
</div>
<script>populate_hosts()</script>
<br/><br/><br/>
<div id="id_services">
<!This
will be populated by the users host selection →
</div>
<br/><br/><br/><br/><br/><br/><br/><br/><br/>
Ignore these two buttons below, they are here by default and don't serve
any purpose in this demo.
';
break; /* End case COMPONENT_CONFIGMODE_GETSETTINGSHTML: */
41. Component Demo - Part 2
componentdemo.js
function populate_hosts() {
var div_to_load = '#id_hosts';
$
(div_to_load).load('/nagiosxi/includes/components/componentdemo/componentdemo_mis
c.php?request=hosts');
}
function populate_services() {
var div_to_load = '#id_services';
var host_selected = $('#id_nagios_hosts').val();
$
(div_to_load).load('/nagiosxi/includes/components/componentdemo/componentdemo_mis
c.php?request=services&host_name=' + encodeURIComponent(host_selected));
}
42. Component Demo - Part 3
Extract from componentdemo_misc.php
case 'hosts':
/* Get the hosts */
$args = array(
'is_active' => 1,
'orderby' => 'host_name:a',
);
/* Returns an XML object, this is NOT an array. */
$xmlhosts = get_xml_host_objects($args);
/* Now create a select of the hosts */
$componentdemo_output .= '<select id="id_nagios_hosts">';
foreach($xmlhosts>
host as $h){
#print_r($h>
host_name . " = " . $h>
address . "<br/>");
$componentdemo_output .= '<option value="'.$h>
host_name.'">'.$h>
host_name.'</option>';
} /* End foreach($xmlhosts>
host as $h){ */
$componentdemo_output .= '</select>';
$componentdemo_output .= '
<br/><br/>
<input type="button" value="Get Host's Services"
onclick="populate_services()">
<br/>
';
break; /* End case 'hosts': */
43. Component Demo - Part 4
componentdemo.js
function populate_hosts() {
var div_to_load = '#id_hosts';
$
(div_to_load).load('/nagiosxi/includes/components/componentdemo/componentdemo_mis
c.php?request=hosts');
}
function populate_services() {
var div_to_load = '#id_services';
var host_selected = $('#id_nagios_hosts').val();
$
(div_to_load).load('/nagiosxi/includes/components/componentdemo/componentdemo_mis
c.php?request=services&host_name=' + encodeURIComponent(host_selected));
}
44. Component Demo - Part 5
Extract from componentdemo_misc.php
case 'services':
/* Get the host name passed to us */
$host_name = urldecode(grab_request_var('host_name',false));
/* Service status fetch, brief listing, sorted by host_name */
$args = array(
'cmd' => 'getservicestatus',
'has_been_checked' => 1,
'host_name' => $host_name,
'is_active' => 1,
'brevity' => 3,
);
/* Returns an XML object, this is NOT an array. */
$statusinfo_services_xml = get_xml_service_status($args);
/* Make sure we've got results to display */
if (count($statusinfo_services_xml>
servicestatus) > 0) {
$componentdemo_output .= '
<table>
<thead><tr><th style="textalign:
left;">Service Name</th><th
style="width:10px;"></th><th style="width:40px;">State</th><th style="textalign:
left;">Status</th></tr></thead>
';
DON'T use
$_GET['xxx']
INSTEAD use
grab_request_var('xxx',false)
45. Component Demo - Part 6
Extract from componentdemo_misc.php
foreach($statusinfo_services_xml>
servicestatus as $service) {
$service_name = "$service>
name";
$current_state = "$service>
current_state";
$status_text = "$service>
status_text";
$componentdemo_output .= '
<tr>
<td>'.$service_name.'</td>
<td> </td>
<td style="textalign:
center;">'.$current_state.'</td>
<td>'.$status_text.'</td>
</tr>
';
} /* End foreach($statusinfo_services_xml>
servicestatus as $service)
{ */
$componentdemo_output .= '</table>';
} /* End if (count($statusinfo_services_xml>
servicestatus) > 0) { */
else {
/* This host does not have any services */
$componentdemo_output .= 'This host does not have any services!';
} /* End else { */
break; /* End case 'services': */
46. Component Demo - Part 7
● You can see how to access the backend API
to get Nagios objects
● Loading DIV's makes this easy and dynamic
48. (¯`·._.· Making It Pretty ·._.·´¯)
● Add a spinning logo that will be displayed
when the AJAX calls are being made
● AJAX = Asynchronous = Complications
● AJAX options will make this work consistently
● The AJAX code will appear differently for the
hosts vs services. This demonstrates different
methods of using the jQuery AJAX (required
because of the encodeuri function)
49. Making It Pretty - Part 1
Extract from componentdemo.inc.php
<div id="id_hosts_throbber" style="display:none">
<br />
'.get_throbber_html().'
</div>
<div id="id_hosts">
<!This
will be populated by the line of script below >
</div>
<script>populate_hosts()</script>
<br/><br/><br/>
<div id="id_services_throbber" style="display:none">
<br />
'.get_throbber_html().'
</div>
<div id="id_services">
<!This
will be populated by the users host selection >
</div>
50. Making It Pretty - Part 2
Extract from componentdemo.js
// This makes an ajax call synchronous
function componentdemo_ajaxSetup() {
$.ajaxSetup({
async: false,
cache: false,
}); // End $.ajaxSetup({
} // End function componentdemo_ajaxSetup() {
function populate_hosts() {
var div_to_load = '#id_hosts';
var div_throbber_id = '#id_hosts_throbber';
$(div_to_load).hide();
$(div_throbber_id).show();
componentdemo_ajaxSetup();
$
(div_to_load).load('/nagiosxi/includes/components/componentdemo/componentdemo_misc.php?
request=hosts',
function() {
$(div_throbber_id).hide();
$(div_to_load).show();
} // End function() {
); // End $(div_to_load).load(
} // End function populate_hosts() {
51. Making It Pretty - Part 3
●While a list of hosts are retrieved a spinning
logo is shown
52. Making It Pretty - Part 4
Extract from componentdemo.js
// This makes an ajax call synchronous
function componentdemo_ajaxSetup() {
$.ajaxSetup({
async: false,
cache: false,
}); // End $.ajaxSetup({
} // End function componentdemo_ajaxSetup() {
function populate_services() {
var div_to_load = '#id_services';
var host_selected = $('#id_nagios_hosts').val();
var div_throbber_id = '#id_services_throbber';
$(div_to_load).hide();
$(div_throbber_id).show();
componentdemo_ajaxSetup();
$
(div_to_load).load('/nagiosxi/includes/components/componentdemo/componentdemo_misc.php',
{
'request' : 'services',
'host_name' : encodeURIComponent(host_selected)
},
function() {
$(div_throbber_id).hide();
$(div_to_load).show();
} // End function() {
); // End $(div_to_load).load(
} // End function populate_services() {
53. Making It Pretty - Part 5
●While a list of services are retrieved a spinning
logo is shown
56. Efficient Coding - Part 2
Extract from the “Status Info Dashlet” available on the Nagios
Exchange
// Define a unique DIV
$statusinfo_inboard_object_container_div = 'statusinfo_inboard_object_container_' .$id;
$output='
<!This
is the DIV that holds the inboard dashlet >
<div id="'.$statusinfo_inboard_object_container_div.'">
'.get_throbber_html().'
</div>
<!create
an anonymous function to refresh the dashlet at the userdefined
interval >
<script type="text/javascript">
<!This
makes the inboard dashlet content do the inital load >
$("#'.
$statusinfo_inboard_object_container_div.'").load("/nagiosxi/includes/dashlets/statusinfo
/statusinfo_inboard.php?
statusinfo_inboard_args='.urlencode(base64_encode(serialize($args))).'");
<!This
makes the inboard dashlet refresh at the userdefined
interval >
setInterval(function() {
$("#'.
$statusinfo_inboard_object_container_div.'").load("/nagiosxi/includes/dashlets/statusinfo
/statusinfo_inboard.php?
statusinfo_inboard_args='.urlencode(base64_encode(serialize($args))).'");
},'.$statusinfo_inboard_refresh_interval.');
</script>
';
58. Troubleshooting – Part 1
● The smallest error in your JavaScipt / jQuery
code can cause everything to break
● Test frequently – don't code 300 lines in one
chunk otherwise you may spend ages working
out where your issue is
● alert() is a simple method for locating where
the issue is occurring
● console.log() is a better debugging method
59. Troubleshooting – Part 2
● Alert example
● alert('It's working and the value of #id_nagios_hosts is: '' + host_selected + ''');
● Tip: Surround values with quotes (helps identify
when you have a blank value)
60. Troubleshooting – Part 3
● console.log() example
● console.log('It's working and the value of #id_nagios_hosts is: '' + host_selected + ''');
● Depending on your browser, access the
console logs with: F12 or CTRL + SHIFT + J
61. Troubleshooting – Part 4
● Comment out lines of code to disable them
● This can help identify where the issue is without
having to remove the code entirely
● It's two forward slashes //
function populate_hosts() {
var div_to_load = '#id_hosts';
var div_throbber_id = '#id_hosts_throbber';
alert('I am up to here');
// $(div_to_load).hide();
// $(div_throbber_id).show();
// componentdemo_ajaxSetup();
// $
(div_to_load).load('/nagiosxi/includes/components/componentdemo/componentdemo_misc.php?
request=hosts',
// function() {
// $(div_throbber_id).hide();
// $(div_to_load).show();
// } // End function() {
// ); // End $(div_to_load).load(
} // End function populate_hosts() {
63. Have A Look At These
AJAX Dependent
Wizards / Components / Dashlets
EMC CLARiiON Monitoring Wizard
Performance Data Tool
Highcharts
Ping Action & Traceroute Action
Google Maps Component & Dashlet
Birdseye
64. Conclusion
● Don't become a baldness statistic
● Keep that lovely head of hair by knowing
JavaScript/jQuery coding techniques
● Learn by
experimenting … take
baby steps
● Go forth and create
awesome Nagios XI
add-ons!
66. The End
Troy Lea aka Box293
tlea@nagios.com
Twitter: @box293
Editor's Notes
First a little about me. I’m primarily a Windows tech starting back in DOS 6 and Windows 3.1. I’ve worked on a variety of support roles over the years ranging from desktop support to enterprise infrastructure administration and now I&apos;ve taken that experience to become a Nagios developer.
I&apos;ve been using Nagios XI since 2009. I originally tried Nagios before XI was released however being a Windows guy there were some linux barriers that I just could not get my head around. It&apos;s funny because this year I made the jump to Linux as my primary OS, using Mint Linux as my core platform.
I love Nagios XI because it is delivered as a virtual appliance. Within minutes of importing that VM and powering it on you have a fully . functional . monitoring . product.
I&apos;ve been developing Nagios related projects since 2010 and let me tell you, if I knew back then what I know now I would have a lot more hair left on my head!
I think the biggest struggle for me was that I knew what I wanted to achieve, but I just didn&apos;t know how to do it. It was especially frustrating when you find code examples on the net that should do what you want but they don&apos;t work for one reason or another.
That is the key take away from this presentation. You will be shown exactly how JavaScript and jQuery work in Nagios XI and what you need to watch out for.
I remember asking a friend of mine how I could make my ideas work with the HTML pages I was developing. He told me that anything you want to occur based on what the user selects on the screen needs to be done with JavaScript or jQuery. My past experiences of JavaScript had not been fun and it was a while before I embraced his advice.
To explain JavaScript I need to set the scene. I&apos;ll use a configuration wizard as an example, specifically the VMware Virtualization Wizard. When you run the config wizard, the end user is presented with some options.
When this web page is generated, it is created on the Nagios XI server using PHP. The page is sent to the user and displayed on their screen. The information on the page is static.
When the user selects an option from a list and clicks a button, this is when JavaScript gets involved. JavaScript sends a request back to the server with some options. The options then tell the server to generate some more HTML content and then send that content back to the user which updates their screen.
JavaScript doesn&apos;t always have to contact the server to update the screen. It can be used to tick a range of boxes on the screen, hide a part of the webpage or show it.
The key concept here is that once the pages are generated by the Nagios XI server, the content in them remains static. The only way to dynamically update the screen is to use JavaScript.
JavaScript is not the easiest language to code in. It can be quite frustrating at times and to do something relatively simple can get quite complex.
My friend that I mentioned earlier told me that jQuery is what JavaScript should have been.
jQuery is a library of functions that make using JavaScript easier.
Now it&apos;s time for the fun to begin!
Here&apos;s some important notes about the files you create, the should be defined as per the slide.
This is a basic example of an alert box being displayed when the user clicks the button.
The &lt;input&gt; has the option “onclick” which calls the JavaScript function.
Everything within the &lt;script&gt;&lt;/script&gt; tags is JavaScript
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;say_hello()&quot;&gt;
&lt;script&gt;
function say_hello() {
alert(&apos;say hello&apos;);
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
This time the onclick action is to send the value &apos;Gday Mate&apos; to the function
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;say_hello(&apos;GDay Mate&apos;)&quot;&gt;
&lt;script&gt;
function say_hello(input) {
alert(input);
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
Comparing the first example with the second example we went from a generic alert box to an alert box that displayed the value which was sent.
The first example requires a JavaScript function for each alert box you want to send.
The second example allows the JavaScript function to be re-used with different messages.
A function is used in coding to group some code together to make coding simpler. You only need to change it in one place … but means all your code that uses the function will be affected!
This example displays an alert box with the value of the select
You can see in the javascript we get the element by the ID and then get the value of that element
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;Value A&quot;&gt;Value A&lt;/option&gt;
&lt;option value=&quot;Option 2&quot;&gt;Option 2&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;select_value(&apos;id_select&apos;)&quot;&gt;
&lt;script&gt;
function select_value(input) {
var the_element = document.getElementById(input);
var the_value = the_element.options[the_element.selectedIndex].value;
alert(the_value);
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
This example performs the same function as the last but is done with jQuery instead.
First we must include the jquery library, otherwise our jQuery calls will do nothing
With jQuery, all of the code goes between the &lt;SCRIPT&gt;&lt;/SCRIPT&gt; tags just like in JavaScript
In jQuery we can do the same thing in one line!
The # refers to an ID element
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;Value A&quot;&gt;Value A&lt;/option&gt;
&lt;option value=&quot;Option 2&quot;&gt;Option 2&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;select_value(&apos;id_select&apos;)&quot;&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script&gt;
function select_value(input) {
var the_value = $(&apos;#&apos; + input).val();
alert(the_value);
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
Compare the two examples and you can see how much clearer and easier jQuery is
It&apos;s much easier to code in a separate JavaScript file and the reasons for this will be explained in later slides. However there are sometimes reasons why you would include the JavaScript code in your HTML file instead and this too will be explained later.
index.html
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;Value A&quot;&gt;Value A&lt;/option&gt;
&lt;option value=&quot;Option 2&quot;&gt;Option 2&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;select_value(&apos;id_select&apos;)&quot;&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;my_javascript.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
my_javascript.js
function select_value(input) {
var the_value = $(&apos;#&apos; + input).val();
alert(the_value);
}
It&apos;s much easier to code in a separate JavaScript file and the reasons for this will be explained in later slides. However there are sometimes reasons why you would include the JavaScript code in your HTML file instead and this too will be explained later.
index.html
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;Value A&quot;&gt;Value A&lt;/option&gt;
&lt;option value=&quot;Option 2&quot;&gt;Option 2&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;select_value(&apos;id_select&apos;)&quot;&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;my_javascript.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
my_javascript.js
function select_value(input) {
var the_value = $(&apos;#&apos; + input).val();
alert(the_value);
}
Whenever you view a web page you are looking at static content. Sure you might click a button and the content on the screen changes, but this is processed at the server and then refreshed on your screen.
So if what you&apos;re seeing on the screen is static, how is it generated on the server?
This is where PHP comes into play. PHP stands for &quot;PHP: Hypertext Preprocessor&quot; (it&apos;s a recursive backronym!).
PHP is a programming language that builds the html content on the fly. This allows for much more complex web pages, and web applications such as Nagios XI.
So instead of having an index.html file we now have an index.php file. No longer do we have a simple HTML coded file but a file full of code that creates the HTML content in a variable and outputs it as a webpage at the end.
And it&apos;s the mix of programming code and HTML code that requires some work-arounds to be implemented as otherwise the webpage will break.
Lets go through the previous examples to demonstrate what I mean.
Here&apos;s that original example but this time it&apos;s in a php file so it looks a little different.
The difference is in the alert line.
We need to escape the single quotes so PHP will ignore the single quotes and simply accept them as plain text.
If we don&apos;t do this then PHP will crash and display a white page.
Explain how carriage returns don&apos;t matter.
Explain how the semi column ends the line.
index.php
&lt;?php
$output = &apos; &lt;!doctype html&gt;&lt;html&gt;&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;say_hello()&quot;&gt;
&lt;script&gt;
function say_hello() {
alert(\&apos;say hello\&apos;);
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&apos;;
print $output;
?&gt;
We are creating a variable called $output which is storing the the HTML code we are generating. When creating a variable full of text it is enclosed between single or double quotes.
When we are adding JavaScript code that has single or double quotes, PHP thinks that is the end of the $output variable we are defining. Because it isn&apos;t, PHP doesn&apos;t understand the characters that follow it and it fails because it&apos;s not correct PHP code. So that is why preceding the quotes with a forward slash (called escaping) is required, it tells PHP to treat the next character as plain text.
This is why storing your JavaScript code in a separate JavaScript file makes programming easier, it becomes less complicated. However you&apos;ll still need to escape single quotes when sending values to a JavaScript function.
You can see here that we needed to escape the single quotes:
onclick=&quot;select_value(\&apos;id_select\&apos;)&quot;
index.php
&lt;?php
$output = &apos;&lt;!doctype html&gt; &lt;html&gt; &lt;head&gt;&lt;meta charset=&quot;utf-8&quot; /&gt;&lt;title&gt;Demo&lt;/title&gt;&lt;/head&gt; &lt;body&gt;Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;Value A&quot;&gt;Value A&lt;/option&gt;
&lt;option value=&quot;Option 2&quot;&gt;Option 2&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;select_value(\&apos;id_select\&apos;)&quot;&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;my_javascript.js&quot;&gt;&lt;/script&gt; &lt;/body&gt; &lt;/html&gt;
&apos;;
print $output;
?&gt;
my_javascript.js
function select_value(input) {
var the_value = $(&apos;#&apos; + input).val();
alert(the_value);
}
Here is the separate JavaScript file.
You can see here that we needed to escape the single quotes:
onclick=&quot;select_value(\&apos;id_select\&apos;)&quot;
index.php
&lt;?php
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;Value A&quot;&gt;Value A&lt;/option&gt;
&lt;option value=&quot;Option 2&quot;&gt;Option 2&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;select_value(\&apos;id_select\&apos;)&quot;&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;my_javascript.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
print $output;
?&gt;
my_javascript.js
function select_value(input) {
var the_value = $(&apos;#&apos; + input).val();
alert(the_value);
}
I made this statement earlier:
When creating a variable full of text it is enclosed between single or double quotes.
$test = &quot;Hello There&quot;;
$test = &apos;Hello There&apos;;
And you&apos;ve noticed all my examples so far I use single quotes when defining variables.
The difference between the two is as follows:
Double quotes = The content between the double quotes can contain PHP variables, which allows the content to be different depending on the value of the variables.
For example:
$food_item = &quot;pizza&quot;;
$output = &quot;My favourite food is $food_item&quot;;
Which means $output will now contain:
My favourite food is pizza
Single quotes = The content between the single quotes is treated as plain text (literal)
$output = &apos;My favourite food is $food_item&apos;;
Which means $output will now contain:
My favourite food is $food_item
So then why don&apos;t I use double quotes like:
$output = &quot;HTML content&quot;;
Then we won&apos;t have to escape those single quotes right?
Yes, you won&apos;t need to escape the single quotes however you&apos;ll need to escape all the double quotes, and in HTML code that&apos;s a lot. Here&apos;s that same JavaScript alert example with double quotes escaped:
&lt;?php
$output = &quot;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=\&quot;utf-8\&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;input type=\&quot;button\&quot; value=\&quot;Click Me\&quot; onclick=\&quot;say_hello()\&quot;&gt;
&lt;script&gt;
function say_hello() {
alert(&apos;say hello&apos;);
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&quot;;
print $output;
?&gt;
So now you can see that while I didn&apos;t need to escape two single quotes, I needed to escape eight double quotes!
&lt;?php
$output = &quot;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=\&quot;utf-8\&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;input type=\&quot;button\&quot; value=\&quot;Click Me\&quot; onclick=\&quot;say_hello()\&quot;&gt;
&lt;script&gt;
function say_hello() {
alert(&apos;say hello&apos;);
}
&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&quot;;
print $output;
?&gt;
This example demonstrates how content can be hidden and shown depending on the users&apos; choices.
index.php
&lt;?php
$output = &apos;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;one&quot;&gt;Strawberry&lt;/option&gt;
&lt;option value=&quot;two&quot;&gt;Grape&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;show_item(\&apos;id_select\&apos;)&quot;&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;div id=&quot;id_one&quot; class=&quot;foods&quot; style=&quot;display:none;&quot;&gt;
&lt;img src=&quot;food-strawberry.png&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;id_two&quot; class=&quot;foods&quot; style=&quot;display:none;&quot;&gt;
&lt;img src=&quot;food-grapes.png&quot;&gt;
&lt;/div&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;my_javascript.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&apos;;
print $output;
?&gt;
my_javascript.js
function show_item(input) {
var item_selected = $(&apos;#&apos; + input).val();
$(&apos;.foods&apos;).hide();
$(&apos;#id_&apos; + item_selected).show();
}
When the user first loads the page, the select list and button is all that is shown.
When the user selects an item and clicks the button, the relative image is shown.
The images themselves are stored inside a &lt;DIV&gt; &lt;/DIV&gt;. When the page is loaded, the DIVs are hidden so the images don&apos;t appear.
All the JavaScript is doing here is hiding both DIVs (using the food CLASS) and then only showing the required DIV (using the DIV ID).
A DIV is a container. You can put content in the DIV, style it etc. You can put DIVs inside of DIVs. You will see shortly how you can load a DIV with content using ajax.
Explain that the whole page exists and has already been created, images already downloaded etc
index.php
&lt;?php
$output = &apos;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;one&quot;&gt;Strawberry&lt;/option&gt;
&lt;option value=&quot;two&quot;&gt;Grape&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;show_item(\&apos;id_select\&apos;)&quot;&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;div id=&quot;id_one&quot; class=&quot;foods&quot; style=&quot;display:none;&quot;&gt;
&lt;img src=&quot;food-strawberry.png&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;id_two&quot; class=&quot;foods&quot; style=&quot;display:none;&quot;&gt;
&lt;img src=&quot;food-grapes.png&quot;&gt;
&lt;/div&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;my_javascript.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&apos;;
print $output;
?&gt;
my_javascript.js
function show_item(input) {
var item_selected = $(&apos;#&apos; + input).val();
$(&apos;.foods&apos;).hide();
$(&apos;#id_&apos; + item_selected).show();
}
The term Ajax has come to represent a broad group of Web technologies that can be used to implement a Web application that communicates with a server in the background, without interfering with the current state of the page.
For example, when the user clicks a button to perform an action, the end users&apos; web browser uses JavaScript to issue a request to the server the page is located on. This request can include information that will allow the server to send back HTML content which will then display on the same web page. This all happens in the background, and it usually indicated with a spinning logo of some sort.
This is the hide and show example by using AJAX.
NOTE: There are THREE files used now
index.php
&lt;?php
$output = &apos;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;one&quot;&gt;Strawberry&lt;/option&gt;
&lt;option value=&quot;two&quot;&gt;Grape&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;load_content(\&apos;id_select\&apos;)&quot;&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;div id=&quot;id_content&quot;&gt;
&lt;!-- this will be populated later --&gt;
&lt;/div&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;my_javascript.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&apos;;
print $output;
?&gt;
content.php
&lt;?php
$selection = $_GET[&apos;selection&apos;];
if ($selection == &apos;one&apos;) {
$output = &apos;&lt;img src=&quot;food-strawberry.png&quot;&gt;&apos;;
}
elseif ($selection == &apos;two&apos;) {
$output = &apos;&lt;img src=&quot;food-grapes.png&quot;&gt;&apos;;
}
print $output;
?&gt;
my_javascript.js
function load_content(input) {
var item_selected = $(&apos;#&apos; + input).val();
var div_to_load = &apos;#id_content&apos;;
$(div_to_load).load(&apos;content.php?selection=&apos; + item_selected);
}
This is the hide and show example by using AJAX.
NOTE: There are THREE files used now
index.php
&lt;?php
$output = &apos;
&lt;!doctype html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;meta charset=&quot;utf-8&quot; /&gt;
&lt;title&gt;Demo&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;
Blah blah blah
&lt;br/&gt;&lt;br/&gt;
&lt;select id=&quot;id_select&quot;&gt;
&lt;option value=&quot;one&quot;&gt;Strawberry&lt;/option&gt;
&lt;option value=&quot;two&quot;&gt;Grape&lt;/option&gt;
&lt;/select&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;input type=&quot;button&quot; value=&quot;Click Me&quot; onclick=&quot;load_content(\&apos;id_select\&apos;)&quot;&gt;
&lt;br/&gt;&lt;br/&gt;
&lt;div id=&quot;id_content&quot;&gt;
&lt;!-- this will be populated later --&gt;
&lt;/div&gt;
&lt;script src=&quot;jquery-2.1.1.min.js&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;my_javascript.js&quot;&gt;&lt;/script&gt;
&lt;/body&gt;
&lt;/html&gt;
&apos;;
print $output;
?&gt;
content.php
&lt;?php
$selection = $_GET[&apos;selection&apos;];
if ($selection == &apos;one&apos;) {
$output = &apos;&lt;img src=&quot;food-strawberry.png&quot;&gt;&apos;;
}
elseif ($selection == &apos;two&apos;) {
$output = &apos;&lt;img src=&quot;food-grapes.png&quot;&gt;&apos;;
}
print $output;
?&gt;
my_javascript.js
function load_content(input) {
var item_selected = $(&apos;#&apos; + input).val();
var div_to_load = &apos;#id_content&apos;;
$(div_to_load).load(&apos;content.php?selection=&apos; + item_selected);
}
So what is happening here is the JavaScript is sending the server an Ajax request, and in that request it is sending the users selection. The content.php file is then grabbing that selection and checking the value. Depending on the value depends on what HTML content is generated and sent back.
When we use the jQuery function &quot;.load&quot;, we are replacing whatever was in the div with new content.
Everything up to this point was demonstrated on a simple Apache Tomcat web server, this was to just demonstrate basic functionality with JavaScript, jQuery and PHP.
Now we&apos;ll go through some more examples that are implemented on Nagios XI.
We&apos;ll use a component to perform our demo.
The goal will be to show a list of hosts first, and then the user will select a host and request to get all the services for this host.
In this section of code, we have a DIV for the host select and then another DIV for the list of services that will be returned.
After the host DIV we have a javascript code that calls the function populate_hosts
This is the jQuery code with the two functions. Here you can see the populate_hosts simply loads the hosts DIV defined in the last slide
This is an extract from the componentdemo_misc.php file that was called by the AJAX request.
This is where all the backend action happens. We are using a built in function of Nagios XI called get_xml_host_objects. It passes on the argument variables we defined in the array.
Basically we are getting all of the active hosts. Then we loop through the XML object to create a select list of all the hosts.
Finally we add a button that calls the javascript function
This is the jQuery code with the two functions. Here you can see the populate_hosts simply loads the hosts DIV defined in the last slide
One thing I want to point out here is “encodeURIComponent(host_selected)”. What this is doing is sending the value of host_selected as a plain string, this way any special characters will not cause issues. On the next slide I will show you how this is decoded.
So the screenshot here shows you what the page looks like when it is intially loaded after the host DIV has been loaded
This is an extract from the componentdemo_misc.php file that was called by the AJAX request.
This is where all the backend action happens. We are using a built in function of Nagios XI called get_xml_service_status. It passes on the argument variables we defined in the array.
NOTE 1: urldecode(grab_request_var(&apos;host_name&apos;,false)) is how we decode the string we encoded in the jQuery
NOTE 2: grab_request_var(&apos;xxx&apos;,false) is a built in Nagios XI function that replaces $_GET[&apos;xxx&apos;]. This cleans any input variables and prevents security vulnerabilities.
Basically we are getting all of the active services for the host that was selected. Then we loop through the XML object to create a table of all the services.
The rest of the code is on the next slide
This is the remainder of the code that is building the table with the list of services for that host.
Here is an screenshot of what the list of services looks like for the host we selected
The whole point of this example was to show how you can use built in Nagios XI functions to access the backend objects.
So once you&apos;ve mastered the basics, you might want to make it a bit more advanced.
Things like displaying a spinning logo while services are loaded.
However the more items you want to do like this requires us to complicate the code.
The key word in the AJAX ancronymn is “asynchronous”
No we are going to display the spinning logo when the host list is being displayed AND also when the service list is being generated.
All we are doing is adding some hidden DIVs that have the spinning logo image in them. There is a built in Nagios XI function we can use called get_throbber_html() which is a real time saver! We call this this THROBBER
To start of with, when the page loads the throbber DIV&apos;s are hidden using the CSS formatting style=&quot;display:none&quot;.
This is the jQuery code for the loading of the hosts lists.
Firstly there is a function for defining the AJAX settings, specifically we are disabling the asyncronous mode of AJAX as we want the code to execute in order.
The order of the hosts function is:
Initially HIDE the hosts DIV
SHOW the HOST throbber DIV
CALL the AJAX setup function
LOAD the hosts DIV
AFTER the load COMPLETES
HIDE the throbber DIV
SHOW the hosts DIV
Here is an screenshot showing the spinning throbber image to let the user know the page was loading while the list of hosts were being generated
This is the jQuery code for the loading of the services table.
The same function for defining the AJAX settings is used.
The order of the services function is:
Initially HIDE the services DIV
SHOW the SERVICES throbber DIV
CALL the AJAX setup function
LOAD the services DIV
AFTER the load COMPLETES
HIDE the throbber DIV
SHOW the services DIV
NOTE: This time we pass the options as an array {option1:value, option2:value}, this has to do with the encodeURIComponent() function we use which causes JavaScript to chuck a wobbly and break!
Here is an screenshot showing the spinning throbber image to let the user know the page was loading while the list of services was being retrieved.
You also want to try and account for all user choices. Make your code a user friendly as possible to provide the best experience. You can do this by performing checks in your JavaScript code, and if the user did not select all the required options then tell them with an alert box.
Earlier I mentioned that it was easier to put your JavaScript code into a seperate file. However there are cases when this really isn&apos;t that efficient so instead you implement the script inside the HTML.
One example where this can be shown is in the Status Info Dashlet. I created this custom Dashlet to allow users to put the current status of a service on their dashboard and style it to their needs. For example you might want the server room temperate displayed in a large bold font on your monitoring wall.
One feature I implemented in the Dashlet was to allow the user to select the refresh interval of the Dashlet. So every x minutes it would re-load the DIV.
Because you can have multiple Dashlets on the one Dashboard, EVERY Dashlet has a unique randomly generated ID. So the JavaScript code needed to know what when each Dashlet needed to be reloaded. If this was in a separate JavaScript file it would require more complicated code to get these ID&apos;s. So here is how this was coded more efficiently:
When the php code generates the Dashlet, it creates a DIV in that Dashlet to load the contents into. So that DIV is a uniquely named DIV based on the $id of the Dashlet.
By putting the JavaScript code in the HTML, php already knows the randomly generated ID so it can then load the correct DIV with the correct contents on the first load and then also every time the refresh interval is reached.
This changed a complicated 20-something lined JavaScript function into about 3 lines of JavaScript embedded in the HTML.
Also, something else worth mentioning here is how I passed LOTs of settings (like 20)+ as one argument. All the settings for each Dashlet are stored in the backend database as an array. By simply passing this whole array when the JavaScript loads I also saved a lot of complicated code. All of the options are obtained when the loaded page is called. This is:
urlencode(base64_encode(serialize($args)))
When things stop working in JavaScript everything can grind to a halt. The simplest spelling mistake or missing quote can be a show stopper!
One way to avoid a lot of hair pulling is to code slowly. Write a few lines and test it. Don&apos;t code a short story and expect it to work first test as you&apos;ll end up wasting a lot of time working out why it stopped working.
However there are some simple tools available to make the diagnosis of these issues easy. The next few slides will show examples of these tools.
Alert is a JavaScript method of displaying a message on the users screen in a pop up box. There are multiple ways this can be used. The most basic way is an alert message that says “I am here”.
When Javascript stops working, it usually works up to the point where there is an error in the code. So yo can use the alert box to see where the code works and when it stops working. It&apos;s like drawing a line in the sand. If it works, move it down a few lines in the code and try again.
Another method is to display the value of the object you are having issues with. This doesn&apos;t always work as you expect however it can help identify when things are not working. The example on the slide shows how this can be done. NOTE how I have enclosed the value in single quotes.
console.log() is a more advanced method of debugging. I&apos;m sure I could do a whole presentation just on how to use the console log however let&apos;s not get sidetracked.
It&apos;s very similar to providing an alert message however to access the logs you need to use you&apos;re browsers debuging tools to view them. The beauty of console log is that it makes debugging of complex objects much easier.
On the slide here is a similar example of the console log method being used
One last troubleshooting method is to comment out your newly added lines of code. This temporarily stops them from being used by JavaScript however it allows you to leave them in the code.
It think the picture says it all. If George Costanza was a Nagios XI developer, he would have a wonderful head of hair if he had access to this presentation.