Switching Active Tabs Programattically: Jquery/Bootstrap

There are lots of different ways to control visibility of different types of web elements.

I’m working on the web front end of what will eventually become an HL7 message inspection tool.

I’ve set it up so that when the user pastes an HL7 message into the textarea on the #omsg pane,  the results will be pasted into the #parsedmsg pane.  I then want the latter pane to become visible.

I set all this up using bootstrap tabs.

The tab controls are anchors wrapped in list elements.  To show what tab is visible, Bootstrap relies on the class “active” to be added to the parent li tag.

I don’t know if I’m having an off day but I couldn’t figure out how to have that happen when I switched visibility programmatically.

The panes would switch visibility just fine, but I naturally wanted the active tab button to be highlighted.

Instead of toggling visibility of various elements,  I decided to write a function using DOM traversal to simulate clicking the desired button.

I’ll go into more detail below, but this is the function itself.

function activeTab(newtabid) {
$('#lpane > ul > li > a[href="'+newtabid+'"]').trigger('click');
});

The tab controls are contained in a div with the id of “lpane”.  As Bootstrap tabs rely on the href attribute, its easy enough to find which element to click using that particular parameter.

Here is the HTML

<div id="wrapper" class="col-lg-12">
<div id="header" class="col-lg-12">
<h3>HL7 Tool</h3>
</div>
<div id="lpane" class="col-lg-12 centered">
<ul class="nav nav-pills " style="text-align:center;">
	<li role="presentation"><a data-toggle="tab" href="#omsg">Original Message</a></li>
	<li role="presentation" id="lpmsg"><a class="btn" data-toggle="tab" href="#pmsg" href="#">Parsed Message</a></li>
	<li role="presentation"><a class="btn" data-toggle="tab" href="#redset" href="#">Redaction Settings</a></li>
	<li role="presentation"><a class="btn" data-toggle="tab" href="#redmsg" href="#">Redacted Message</a></li>
</ul>
</div>
<div id="cpane" class="tab-content col-lg-12">
<div id="omsg" class="tab-pane active">
<label for="#omsg">Original Message</label><textarea id="msg" class="form-control" placeholder="Paste Msg Here"></textarea>
<input type="button" class="btn" value="Parse" id="parsemsg"/><input type="button" class="btn" value="Clear" id="clearomsg" />
</div>
<div id="pmsg" class="tab-pane">
<div class="col-md-6" id="parsedmsg"></div>
</div>
<div id="redset" class="tab-pane">
REDSET
</div>
<div id="redmsg" class="tab-pane">
REDMSG
</div>
</div>
</div>

and finally…the actual script


<script>

$(document).ready(function(e){
 
$('#parsemsg').click(function(e){
 
$('#parsedmsg').parsehl7({msgin:$('#msg').val()});
 
 activeTab('#pmsg');
 
 }); //parsemsg
 
 }); //document ready

</script>

 

 

CSS Calc Function

 

Have you ever had a problem getting a div to center?   There are times that for some reason the margin: auto;  just doesn’t work.

Its situations like this that get old timers like me poking around Google where we discover new and cool things.   (the whole having a job, and being expected to produce results thing can make that difficult at times).

This led to the discovery of the calc()  function!

Calc allows you to use math to size elements without having to resort to scripting.

In the example below,  I set up a lightbox div with a width that is 100 pixels less than half the width of the parent div  (calc(50% – 100px);).

In order to center this (because margin:auto wasn’t working for some reason),  I used (calc((100% – (50% – 100px))/2);)

 

.lightbox {
margin-top:20px;
 width:calc(50% - 100px);
 left: calc((100% - (50% - 100px))/2);
 height:auto;
 padding:15px;
 margin-left:auto;
 margin-right: auto;
 position:absolute;
 border: #110ef3 solid 2px;
 border-radius: 5px;
 background-color: #FFF;

}

JQuery/HTML: Handling events for elements created after initial page load.

My regular readers already know that I add a lot of stuff to my pages programmatically using PHP. Naturally much of this code is added after the initial page load.

I used to defeat this by loading in the scripting with the new elements, but that’s very tedious, and honestly, sloppy.

The issue is that new elements aren’t registered with the Document Object Model (DOM) set up when the page loads.

To get around that you can sort of “pre-register” these elements using JQuery’s .on method.

Here’s the syntax:


$(document).on([event],[selector],function(e) {

//do your stuff here

});

Here’s a working example from an actual piece of code I’m working on.

In this example I’m posting data to a php script when the target element (id=”edname_1″) loses focus, provided it doesn’t match what’s there already. I do this by loading the contents of the control into txtval on the focusin event.

var txtval = '';    //global variable.
		
		
		    $(document).on("focusin","#edname_1",function(e){
		    	
		    	txtval = $(this).val();   //loads global
		    	
		    });
		
			$(document).on("focusout","#edname_1",function(e){
				
					if ($(this).val() == txtval) {
						console.log("doing nothing");
						return;
						
					}
				
					if($(this).val().length < 1) {
						
						alert("This shouldn't be blank");
						return;
						
					}
				console.log("updating");
				$.post('PHP/updateftable.php', {field: $("#activefld").val(), val: $(this).val()}) 
                                            
                                        /*
                                         In order to avoid having to add the db table primary key of the row I want to update to every element I add to the div,                         
                                         I created a hidden field and placed that key as the value.
                                         */

				.done(function(data){
					
					console.log(data);   //checks the output.
							
				});
				
	
			});
		


This example is from a piece of actual code for a project in development, so there’s some exception handling, etc. I haven’t done yet.

JQuery: Add Rows and Columns to Tables Programmatically

This turned out to be a bit of a bear to search for exactly what I wanted, in such a way that I understood it…so I’m posting here.

The Problem

To create a table which the user could add columns or rows as they required.
New rows must contain the columns added earlier.

There is no requirement to isolate additional columns to specific rows.

The Solution

The example below uses a class selector as there are several tables (also added programmatically).

Adding a column.


$(".sbutc").click(function(e){
		
		var tid = this.id;
		var bid = tid.replace('sbutc_','stable_');   //This points to the appropriate parent table

                //first, I need to know how many rows there are so I can get the number of columns in the last one (skipping header rows)
                //Note that I point to the tbody object,  if you don't use these,  that should be the table id.

		var rows = document.getElementById(bid).getElementsByTagName("tbody")[0].getElementsByTagName("tr").length;
		

		var cols = $('#' + bid + ' tr:nth-child(' + rows + ') td').length;   //get's the number of columns in the last row
		console.log('cols: ' + cols);
		
		$("#" + bid).find('tr').each(function(){                            
						
                $(this).find('td').eq(cols-1).after('<td>new cell added</td>');      //adds the new cell. 
   		}); 

               /*
                You'll note that I subtract 1 from the column count when adding the column.  This is because when pulling the count, it starts with 1, while 
                object indexes always start at 0
               */

This adds the row.


$(".sbutr").click(function(e){
		
		var tid = this.id;
		var bid = tid.replace('sbutr_','stable_');
		var rows = document.getElementById(bid).getElementsByTagName("tbody")[0].getElementsByTagName("tr").length;
		var cols = $('#' + bid + ' tr:nth-child(' + rows + ') td').length; 
		
                
		
		var apstring = '<tr>';             //sets up the string used in the append statement
		
		for(var i=1;i<=cols;i++) {        //adds a td element for each row detected above and appends it to the apstring
			
			apstring += '<td ondrop="drop(event)" ondragover="allowDrop(event)">-</td>';
			
		}
		
		apstring += '</tr>';              //very important!
		
		$('#' + bid + ' > tbody:last').append(apstring);   //append the row to the bottom of the table
		
		
		
	});



I will post a link so you can see it in action when I get a chance (behind a firewall currently).

Quick Tip: Adding PHP content to your html page

If you’re like me and prefer using PHP scripting to enhance web-functionality, an important thing to know is how to add the results of any PHP coding into your web page.

The anatomy of a web page with the extension .php looks like this:

<?php

//your php stuff here (obviously)

?>
<html>
<header>
</header>
<body>
</body>
</html>

I know right now you’re saying, “WOW! That’s amazing! You’ve just created a blank web page that does nothing!” You’d be right of course..but that’s better than creating a web page that isn’t blank that does nothing.

For those of you who don’t like long tutorials and just want the actual code here it is:

<?php
$newtitle = "Proudly titled by PHP script!";
?>
<html>
<header>
<title><?php echo $newtitle; ?></title>
</header>
<body>
</body>

Before I go further, let me warn you about one thing. If you work in PHP you will want to set your error_reporting levels appropriately on public web pages, as if an error is thrown, the user will gain insight into your code, and perhaps find a vulnerability.

Here’s a handy link on how to do that, as its outside the scope of this post.

One of the great things about this method is you can also include HTML tags and what not, giving you almost unlimited flexibility in building the page the user sees.

So, here’s a script that will change the background colour of a web page programmatically. There’s a link at the bottom, so you can see it in action.

 
<?php
$bcol[0] = "#000000";	//black
$bcol[1] = "#33CC66";	//green
$bcol[2] = "#FF3366";	//fuscia (yes, I know what fuscia is
$bcol[3] = "#0000FF";	//blue

rand();		//seed the randomizer

$tc = rand(0,3);

$style = '<style>';
$style .= 'body {';
$style .= 'background-color:'.$bcol[$tc].';';
$style .= '</style>';

?>
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Mood Ring</title>
<?php echo $style; ?>   <!--this is where the code above is added to the webpage -->
</head>
<body>
<span id="txt1" style="font-size:larger;">The background colour is driven by a PHP script</span>
</body>
</html>

In the above example, you’ll see where in lines 11-14, I load the contents of the html style tag into the PHP variable $style (did I ever mention that I’m awesome at naming variables?).

In line 22, I add the contents of $style to the HTML page.

If you view source, this is what you’ll see…

<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>Mood Ring</title>
<style>body {background-color:#FF3366;</style>   <!--this is where the code above is added to the webpage -->
</head>
<body>
<span id="txt1" style="font-size:larger;">The background colour is driven by a PHP script</span>
</body>
</html>

If you’re wondering what happened to the all the PHP stuff, servers will typically strip it out and not send it to the client.

Hopefully this helps you out. If not, leave a comment, and I’ll try and help you out.

Moodring