Limit The Number of Checkboxes 'checked' with jQuery

Quick code snippet. Assume you have:

<p>Best Cheese? Please select the three:</p>
<div>
   <label><input type="checkbox" name="Cheddar" value="1" class="limitThree">Cheddar</label>
   <label><input type="checkbox" name="Cheshire" value="1" class="limitThree">Cheshire</label>
   <label><input type="checkbox" name="Creamy Lancashire" value="1" class="limitThree">Creamy Lancashire</label>
   <label><input type="checkbox" name="Cheshire" value="1" class="limitThree">Double Gloucester</label>
   <label><input type="checkbox" name="Red Leicester" value="1" class="limitThree">Red Leicester</label>
   <label><input type="checkbox" name="Stilton " value="1" class="limitThree">Stilton</label>
   <label><input type="checkbox" name="Wensleydale" value="1" class="limitThree">Wensleydale</label>
</div>

Then you could use the following jQuery:

$('.limitThree').on('change', function(){
	var noChecked = 0;
	$.each($('.limitThree'), function(){
		if($(this).is(':checked')){
			noChecked++;	
		}
	});
	if(noChecked >= 3){
		$.each($('.limitThree'), function(){
			if($(this).not(':checked').length == 1){
				$(this).attr('disabled','disabled');	
			}
		});
	}else{
		$('.limitThree').removeAttr('disabled');	
	};
});

Recursive Javascript Functions

Just posted a codepen if anyone looking at Recursive Javascript functions.  The scenario here could I am sure be tackled other ways but I wanted to do it with a recursive function.

Given an array of random numbers, the function getNewNumber will finish off the array by populating it with the remaining number between 1 and 10, done in a random order.

var bunchOfNumbers = [1,4,5];
var getNewNumber = function(){
    var tempNo = Math.ceil(Math.random()*10);
    tempNo ? 11 : tempNo--;
    for (var i = 0; i < bunchOfNumbers.length; i++) {
        if (bunchOfNumbers[i] == tempNo) {
          document.getElementById('error').innerHTML += "Number in use:"+tempNo+"<br>";
           return getNewNumber();
        }
     }
    bunchOfNumbers.push(tempNo);
    if(bunchOfNumbers.length < 10){
      return getNewNumber();
    }else{
      return true;
    }
}
getNewNumber();
console.dir(bunchOfNumbers);
document.getElementById('msg').innerHTML = bunchOfNumbers.toString();

I needed a version of this for ensuring an object was not placed at the same coordinates as other objects in an array of coordinates.

View Codepen

Post Script

Some more thoughts on this. Here is an example that checks to see if a PIN number is unique. I am using Firebase to store the PINs.

var getNewNumber = function(){
  var newPin;
  newPin = Math.round(Math.random()*100000)+10000;
  newPin = String(newPin);
  newPin = newPin.substring(1, 5);
  db.ref('cpUsers/').orderByChild("pin").equalTo(newPin).on("value", function(snapshot){
	if(snapshot.val() === null){
             db.ref('cpUsers/').push({pin: newPin}).then(function(snapshot){
	     return snapshot.key;
	     },function(error){console.info(error)});
	}else{
	    return getNewNumber;
	}
   });
}

Validating Radio Buttons Using Javascript (jQuery)

In online surveys you may want users to have to answer a radio button style question. You can set a default value with checked as follows:

<input id="female" name="gender" type="radio" value="F" checked>
<label for="female">Female</label>
<input id="male" name="gender" type="radio" value="M">
<label for="male">Male</label>

However, you have to make a decision what the default with be and for lazy form fillers you might end up with incorrect data.

In HTML5 radio buttons we can use the required attribute ie

<input id="female" name="gender" type="radio" value="F" required>
<label for="female">Female</label>
<input id="male" name="gender" type="radio" value="M">
<label for="male">Male</label>

This is great but comes with the inevitable HTML5 caveats that it just can't be relied on across all browsers.

So for true radio button validation we need a Javascript solution .... and as ever I've used jQuery here to help.

The HTML/CSS Set Up

Firstly lets add some HTML to provide error messages.

<input type="radio" name="gender" value="F" id="female">
<label for="female">Female</label>
<input id="male" name="gender" type="radio" value="M" />
<label for="male">Male</label>
<span class="error"> *Required</span>

The <span> needs to be hidden initially so in the CSS we'll add:

.error{
display:none;
}

The Javascript

The jQuery is called when the form is submitted. For those in a hurry here is the code:

$('form').submit(function() {
	 $('.error').hide();
	  var radioList = $('input:radio');
	  var radioNameList = new Array();
	  var radioUniqueNameList = new Array();
	  var notCompleted = 0;
	  for(var i=0; i< radioList.length; i++){
		  radioNameList.push(radioList[i].name);
	  }
	  radioUniqueNameList = jQuery.unique( radioNameList );
	  for(var i=0; i< radioUniqueNameList.length; i++){
		  if(typeof($('input:radio[name='+radioUniqueNameList[i]+']:checked').val()) === "undefined"){
			  $('input:radio[name='+radioUniqueNameList[i]+']').parent().find('.error').show();
			  notCompleted++;
		  }
		}
	 if(notCompleted > 0){
		 return false;
	 }else{
		 return true;
	 }
});

View CodePen

How it works?

The Javascript firstly switches off all the .error messages just in case one is already live.

$('.error').hide();

Next a list of the radio buttons is created:

var radioList = $('input:radio');

This will give me a list of all the radio buttons. What we really want are the radio groups. So in order to get this two arrays are created to store all the names and then refine that list of the unique names.

Looping around the radioNameList array we populate radioNameList with all the names. Then jQuery.unique allows use to refine this to an unique list.

Once we have this list of unique radio group names we can loop these checking to see there is a checked value in each group. If a radio group does not have a checked value undefined is returned. When this happens by navigating the DOM we can switch on the related .error message.

The notCompleted variable is used to keep count of things. So if the number of non-completions is greater than zero the form isn't submitted.

This may seem over engineered but it is designed so that multiple radio button groups can be validated. Here is a fuller example:

View Demo

This can probably be refactored so comments welcomed to refine the idea.

Lazy form fillers - lazy line painters.

Adding Form Fields Dynamically with Knockout.js

A couple of years ago I did a post entitled Adding Form Fields Dynamically with jQuery.  In this post I am going to re-visit the same problem but this time use Knockout.js to create the dynamic form fields.

View The Demo

Introducing Knockout.js

Knockout.js is a Model-View-View-Model Javascript library. What it excels at is 'binding' data such as Javascript objects, arrays and JSON to your output HTML. To use Knockout.js take a trip to knockoutjs.com to view their excellent tutorials and documentation. To use it you need to either download the Knockout.js file or you can use a distributed version of the file by adding:

<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/3.1.0/knockout-min.js">
</script>

Data Binding

Knockout.js works by 'binding' your data model to your HTML output. The hook it uses for this are HTML's custom attributes. Primarily this is done by declaring a data-bind on a HTML element and then adding some knockout.js logic to it.

<div data-bind="someCommand">

Note: HTML attributes are part of the HTML5 specification but you can safely use in both newer HTML5 browsers as well as older ones.

In our example we are going to set up the HTML form as follows:

<form method="post">
<div data-bind="foreach: myFieldList">
  <p>
  <label data-bind="text: label"></label>
  <input data-bind="attr: { name: fname}">
  <span class="removeVar" data-bind="click: removeField">Remove Variable</span>
   </p>
</div>

<p>
<span id="addVar" data-bind="click: addField">Add Variable</span>
</p>

<p class="alignRight">
<input type="submit" value="Check">
</p>

</form>

Notice the use of the data-bind custom attribute to bind various Knockout.js commands to the HTML elements

The Javascript itself consists of:

function fieldModel(){
        var self = this;
	var noTracker = 3;
	self.myFieldList = ko.observableArray([{label : "Variable 1", fname : "var1"},{label : "Variable 2", fname : "var2"},{label : "Variable 3", fname : "var3"}]);

	self.removeField = function(dynamicField){
	    self.myFieldList.remove(dynamicField);
	}

	self.addField = function() {
	    noTracker++;
	    self.myFieldList.push({label : "Variable "+ noTracker, fname : "var"+ noTracker});
    	}
}
ko.applyBindings(fieldModel);

Primarily this is involved in creating a data model fieldModel with initial properties as well as a couple of methods removeField and addField. This is fundamentally 'vanilla' Javascript apart from ko.observableArray which is Knockout's extended version of an array that makes it easier to manipulate, and the ko.applyBindings(fieldModel); that 'binds' our data model to the HTML above.

Creating Files with PHP via fopen(), fwrite(), fclose() and copy()

On a recent project I was getting some pages that were causing PHP to run slow.  Essentially the PHP was looping through various tables in the MySQL table to build a rather complex 'Mega Menu' navigation system.  As this navigation system was needed on all the pages of the site this was causing difficultly.  The site's Content Management System allowed the site user to add items to this menu system but this was done infrequently, so continually re-building of the menu system was pretty inefficient.  Therefore I rewrote the code so that when the data underlying the navigation system was amended in the Content Management System, a new include file would be built as a permanent file rather than a dynamic file.

This required the use of some of PHP's file creation tricks, essentially fopen to open/create the file and then fwrite to write data to the file. Once the data is written to the file we close it up with fclose.

// name the file
$File = "nav.inc.php";
$Handle = fopen($File, 'w');
$data = '<nav class="sixteen columns remove-bottom">'
// PHP logic to build the navigation from the database
$data .= '</nav>';
// write the data to the file
fwrite($Handle, $data);
fclose($Handle);

You can also use copy to move a file. This was useful to move the file to the location I wanted in my server file structure.

Strictly Javascript

There comes a time with a large Javascript project where having the code behave more like a 'usual' programming language becomes useful.  This is where 'strict mode' comes in.

Javascript is very forgiving.  Take the following:

myMsg = "Hiya";

No problem.  Yet programming from other languages will throw their arms in horror - The Variable has not been declared! We have a variable without declaring it with the var keyword.  If you want to enforce the use of the var keyword, to for example keep track of scope, then you can add the following:

'use strict'
myMsg = "Hiya";

The above will throw an error.  However if we amend the code to:

'use strict'
var myMsg;
myMsg = "Hiya";

This will be valid as the variable has been properly declared with var.

JS Fiddle

Scope

You can limit the 'strictness' to a function by declaring 'use strict' inside a function so that the strict rules only apply to that function ie:

function showMsg(){
    // only strict in the function
    'use strict'
    var myMsg1 = "local stuff"; 
    return myMsg1;
}

JS Fiddle

Beyond the declaration of variables strict mode will also add restrictions such as:

  • Preventing writing to read only properties
  • Stopping the extension of non-extensible objects
  • Preventing the duplication of object literal properties
  • Preventing the use of 'future' reserved words such as a 'public', 'static' and 'private'

For more information see MSN on Strict Mode

Four for out the Door - Essential PHP Extensions to finish that project

Image Manipulation

When uploading images this handy PHP extension will allow you to manipulate images on the fly - resizing, renaming, change format and even add effects.

PHP Image Magician

PDF Generation

Generate PDF's on the fly based on the content of your MySQL database.

TCPDF

Excel Generation

Generate Excel files on the fly based on the content of your MySQL database.

phpexcel

Email

Go beyond the simple PHP mail function with swiftmailer. You can even attached your dynamically created Excel or PDF as an attachment.

swiftmailer

Not PHP but what the heck if you want a robust HTML formatted email that will work across all those pesky mail clients, phones, tablets, fridges then Zurb have these handy templates.

HTML Email Templates for Zurb

Storing Values with Javascript's localStorage

As part of the range of new HTML5 Javascript goodies localStorage allows developers to store data client side for later reuse. Sounds familiar? Yep, just like cookies, but without the size limitations as you can store Megabytes of data using localStorage.

Setting Values

To set a localStorage value you use the method setItem().

localStorage.setItem(name,value);

So to set a value of 'Creamy Lancashire' to an item named 'cheese' we would use:

localStorage.setItem('cheese','Creamy Lancashire');

Getting Values Back

To get values back from localStorage we use the getItem() with the syntax:

localStorage.getItem(name);

So the cheesy example would be:

var perfectWithBiscuits = localStorage.setItem('cheese');

Optional extra info on getters and setters (Tell me more)

Getters and Setters

An alternative to the methods of setItem() and getItem() is to use the 'name' as a getter/setter. An alternative way to get and set values would therefore be:

// to set
localStorage.cheese = 'Creamy Lancashire');
// to get
var perfectWithBiscuits = localStorage.cheese;

Both should be supported but as ever check with your target browsers. One difference is the messages returned when the values are not set. The setItem() method returns null whilst the getter returns undefined.

View Demo

An Example with a Colour Picker

In this demo localStorage is used to store the background colour you pick, such that when you return to the page after closing the browser it remembers your choice.

//set value
localStorage.myBgColour=newColour;
//get value
bgColour = localStorage.myBgColour

The rather neat Javascript Colour picker here comes courtesy of Spectrum.

View Demo

Dividing Dynamic Content equally into Columns

The CSS float property is often used to create columns. Waiting in the wings are some newer techniques such as the CSS column-count property which will make adding columns much easier.

For example given a HTML snippet of :

<ul>
<ul>
	<li>ALFA ROMEO</li>
	<li>AUDI</li>
	<li>AUSTIN</li>
	<li>BMW</li>
        .. etc etc
        <li>TOYOTA</li>
	<li>TRIUMPH</li>
	<li>VAUXHALL</li>
	<li>VOLKSWAGEN</li>
	<li>VOLVO</li>
</ul>

We can use the following CSS to put the list into 5 nice columns.

	column-count:5;
	column-gap:40px;
	column-rule-width:1px;
	column-rule-style:outset;
	column-rule-color:#ccc;

View Demo

This is particularly useful when your content (in this case a list) is dynamic and you don't know how many items you're doing to have and therefore how many items to place in each list.

A Javascript Fallback

However, as caniuse kindly tell us we can't use this technique with IE9 or earlier.

Here is a solution I came up with. Assuming we want 5 columns set up the HTML as follows:

<div id="colsContainer">
 	<div><ul></ul></div>
	<div><ul></ul></div>
	<div><ul></ul></div>
	<div><ul></ul></div>
	<div><ul></ul></div>
</div>

The dynamic data I am going to use here is a Javascript array.

var myArray = new Array('ALFA ROMEO','AUDI','AUSTIN','BMW', .... 'VOLKSWAGEN','VOLVO');

The following Javascript counts the number of values in the array and then works out how to distribute them evenly across, in this case, five columns. The maths trick here is the use of the modulus (%) to divide the items by the number of columns but distribute the remainder to the left-hand columns.

 var noCols = 5;
 var displayData = "";
 var startVal = 0;
 var endVal = 0;
 for(var i=0;i<noCols;i++){
     if(i < myData.length%noCols){
         endVal =+ (endVal+Math.floor(myData.length/noCols)+1);
     }else{
         endVal =+ (endVal+Math.floor(myData.length/noCols));
     }
     displayData = ""
     for(var j=startVal;j<endVal;j++){
         displayData += '<li><a href="">';
         displayData += myData[j];
         displayData += '</a></li>';
     }
     startVal = endVal;
     $('#modelList div ul').eq(i).html(displayData);
 }

View Demo

Cleaning out Smart Curly Quotes with PHP

Smart curly quotes are the bane of my life and they most commonly cause grieve when users cut and paste from Microsoft Word into a web form and you end up with the funny box shapes.

This code was on toao.net and I've just added it to a function.


function cleanCurlies($string){
 $string = str_replace(array("\xe2\x80\x98", "\xe2\x80\x99", "\xe2\x80\x9c", "\xe2\x80\x9d", "\xe2\x80\x93", "\xe2\x80\x94", "\xe2\x80\xa6"), array("'", "'", '"', '"', '-', '--', '...'), $string);
 // Next, replace their Windows-1252 equivalents.
 $string = str_replace(array(chr(145), chr(146), chr(147), chr(148), chr(150), chr(151), chr(133)), array("'", "'", '"', '"', '-', '--', '...'), $string);
 return $string;
}

Original found here: http://www.toao.net/48-replacing-smart-quotes-and-em-dashes-in-mysql