Category: jQuery


I’ve spent almost a week and so just figuring out on how to be able to use icons as point values on the chart. Thanks to this post , it worked like a charm. I did made some additional coding to make it possible to display an icon over the chart.

Here is the code:

On your index page or from the page the flot is located.


var options = {

points: { show: true, radius: 3, type: "o" }

/* Note I added the "type" with either x or o value, in order to set it to the usual circle (which is "o") or custom image (which is "x") */
...


On the jquery.flot.js file, search for ” function plotPoints(” this is where we will update and do some coding…



function plotPoints(datapoints, radius, fillStyle, offset, circumference, axisx, axisy) {
                
var points = datapoints.points, ps = datapoints.pointsize;
                
	for (var i = 0; i < points.length; i += ps) {
      	var x = points[i], y = points[i + 1];
            if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max)
            continue;
            
/* Below this line is where we start to do some additional coding...*/   
  
                  if(series.points.type == "x") {
                	
                	  customimage(axisx.p2c(x)-1,axisy.p2c(y)-11);

	              /* we call the function to retrieve and display the image*/
                  
					
			} else if(series.points.type == "o") {
					
				ctx.beginPath();
				ctx.arc(axisx.p2c(x), axisy.p2c(y) + offset, radius, 0, circumference, true);
	                    if (fillStyle) {
	                        ctx.fillStyle = fillStyle;
	                        ctx.fill();
	                    }
	                    ctx.stroke();
			} 
                  
                
               }
            }

/* this is the function that I added to draw the image on the chart canvass*/

function customimage(x,y){

	var img = new Image();
        	
	img.onload = function() {

      ctx.beginPath();    
      ctx.drawImage(img,x,y,24,34);
      ctx.closePath();
      ctx.stroke();

      }
     img.src = 'star.jpg';  	
}

Regarding the LEGEND part of the chart. I’ve made some additional updated to in order to display a thumbnail of the icon beside the Label name.

On the jquery.flot.js file, search for ” function insertLegend(” this is where we will update…


if (i % options.legend.noColumns == 0) {
                    if (rowStarted)
                        fragments.push('</tr>');
                    fragments.push('<tr>');
                    rowStarted = true;
}

if (lf)
/* Below this line is where I made some updates. */                    
               
if (label != 'Star'){  
/* Star is the sample Label name. you can edit it and change it to the actual label name */

	label = lf(label, s);
	fragments.push('<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:13px;height:13px;background-color:' + s.color + ';overflow:hidden"></div></div></td>' +'<td class="legendLabel">' + label + '</td>');

} else {
/* this is where I add the image source of the star icon */
	fragments.push('<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:13px;height:13px;overflow:hidden"><img src="star.jpg"/></div></div></td>' +
'<td class="legendLabel">' + label + '</td>');

}

So that’s about it :) Hope to be of help again, one way or another. Feel free to correct me or add any suggestions.

One thing that is essential in having a calendar for a web application is the capability to have a go to date that will enable a user to go directly and display a specific date. On the FullCalendar plugin, I made use of the gotoDate method. It is not complicated, you just have to create a form that will ask a user to input the desired date to view, and a javascript function that will trigger the gotoDate method.

Note: I advise you to read my previous post ( CakePHP and jQuery FullCalendar plugin (Part I – Retrieve events from database)) first regarding this plugin.

Add this to your index page where the calendar is displayed. (ie. app/views/calendar/index.ctp)


<script type='text/javascript'>


function gotodate(userdate){
  
var dateinput = new Date(userdate); // userdate is what the user has inputted.

$('#calendar')
     	.fullCalendar('changeView', 'basicDay')  // we called the changeView method to display basicDay view.
     	.fullCalendar('gotoDate', dateinput);  // here's where we call the gotoDate method to do the magic.

}

</script>

Hope this helps! If you have any suggestions or corrections feel free to do so :) By the way, you could also check out Part I – Retrieve from database and Part II – Editable feature :)

FullCalendar plugin has an editable feature that makes it possible to update events by dragging and dropping posts anywhere within the calendar. This time, I’ll be sharing on how I’ve utilized this feature, as well as on how to update the events on the database.

Note: I advise you to read my previous post ( CakePHP and jQuery FullCalendar plugin (Part I – Retrieve events from database)) first regarding this plugin.

So let’s begin!

Add this to your index page where the calendar is displayed. (ie. app/views/calendar/index.ctp)


// include this in the FullCalendar script...

editable: true,

eventDrop: function(event) {	// Make sure to read the plugin's documentation :)

var dt = new Date(event.start);   // event.start is the new date where you dragged and dropped the event post.
var yr = dt.getFullYear();
var dy = dt.getDate();
var mth = dt.getMonth()+1;
var hrs = dt.getHours();
var mns = dt.getMinutes();

var newdate = yr+'-'+mth+'-'+dy;  // pass this date to the database via post.

$.post("http://www.yoursite.com/calendar/edit/id:"+event.id+"/date:"+newdate, function(data){});

} 

On your controller (ie. app/controllers/calendar_controller.php), create the edit function.


function edit($id=null){

$this->Event->id = $this->params['named']['id'];
 // By the way I made use of the params to get the values.
$this->Event->saveField('event_date',$this->params['named']['date']);

}

So that’s about it. :) You can also use the eventResize: function(), this feature will let you resize or extend the date duration of an event.

Also check out Part I – Retrieve from database and Part III gotoDate method :)

This week I’ve incorporated the jQuery’s FullCalendar plugin to the project I’m working. It was a bit challenging task but really glad to make it worked. :) I hope to help someone and share what I did to make this task possible.

First, I assume that you have already checked out the FullCalendar demo and downloaded the source code. You’re now in the process of incorporating it to your web application.

So to get things started, you need to include the jQuery script and FullCalendar script plus css in your default layout page. (ie. app/views/layout/default.ctp)

<?php echo $javascript->link('jquery-1.3.2'); ?>
<?php echo $javascript->link('fullcalendar.min'); ?>

// jquery ui purpose for this has something to do with the editing part of the FullCalendar plugin

<?php echo $javascript->link('ui.core'); ?> 
<?php echo $javascript->link('ui.draggable'); ?>
<?php echo $javascript->link('ui.resizable'); ?>

<?php echo $html->css('fullcalendar'); ?> 

On your controller, let’s create the code that will retrieve calendar events from the database. (ie. app/controllers/calendar_controller.php)


function index() {

// get all the events from the database.
$events = $this->Event->find('all');

// insert rows to an array.
for ($a=0; count($events)> $a; $a++){

$rows[]= '{"id":'.$events[$a]['Event']['id'].', "title":"'.events[$a]['Event']['name'].'", "start":"'.$events[$a]['Event']['event_date'].'", "className":"'.$events[$a]['Event']['type'].'","type":"'.$events[$a]['Event']['type'].'"}';

}

// convert the array to a string.
if ($rows){
$convertojson = implode(",", $rows);
}

// pass the string to the json variable. this will then be passed  and printed to the javascript code.
$this->set('json',"[".$convertojson."]"); 

}

On your views add the index page for displaying the calendar. (ie. app/views/calendar/index.ctp )


<script type='text/javascript'>

$(document).ready(function() {
	 
$('#calendar').fullCalendar({
		
	header: {
		left: 'prev,next today',
		center: 'title',
		right: 'month,agendaWeek,agendaDay'
		},
	events: <?php echo $json; ?> // this is where we call the php variable
	
});
)};
</script>

<div id='calendar' style='width: 900px; margin: 0 auto;'></div>

So that’s it! You could also check out Part II – Editable feature and Part III gotoDate method :)

I recently worked on incorporating validation for importing CSV type of file. Since I’m already using the Valid8 (jQuery) plugin, I just made used of it and found a way to validate file extensions.

By the way, before you even go further I suggest you read the documentation of the plugin first. :)

So to get things started, you need to include the jQuery script and Valid8 (jQuery) plugin in your default layout page. (For me it was the default.ctp, ie. app/views/layout/default.ctp)

<?php echo $javascript->link('jquery-1.3.2'); ?>
<?php echo $javascript->link('jquery.valid8-1.2.2'); ?>

Then go to your views page where you need to do the validations. (ie. app/views/posts/import.ctp). Basically what I added was the custom function ( confirmFiletype() ) that will validate if the file extension was true or not, depending on what type of file you need to restrict. For me, what I need was to make sure that the type of file is CSV format.

 
<script>

$('#submit').click(function(){
if ( $('#PostFile').isValid() != true){
 $('#PostFile').focus();
return false;
}
});


$('#PostFile').valid8({	regularExpressions: [
		{expression: /^.+$/, errormessage: 'Inserting a file is required'}
		],
		jsFunctions:[
		{ 'function': confirmFiletype, 'values': function(){
			return {filetype: $('#PostFile').val()}
		}}
		]
});

      
function confirmFiletype(args){
var str=args.filetype;
if(str.lastIndexOf(".csv")==-1) // I made used of the lastIndexof and check if the file was with the extension csv on it.
return {valid:false, message:'File must be in csv format.'}
else
return {valid:true}
}

</script>

<?php 

echo $form->create('Lead', array('enctype' => 'multipart/form-data', 'action' => 'import') ); 

echo $form->file('Lead.File');

echo $form->end('Import');

?>

So that’s it. Hope this helps :)

Preloader image is useful when a page needs some more time before the entire content loads. It will give the user the hint that the page is not yet done loading. Here is what I did recently with the application I’m doing.

Add this to your jQuery script…


$('#content').html('<img src="/img/loading.gif"/>'); // this is where you add your loading animation.
$("#content").load("http://www.yoursite.com/about"); // by the way, what I did here is to get a page remotely.

Simple as that :)

CakePHP and jQuery

With the project I’m working on right now, I needed to make the details page clickable and edit in place (no need to display another page with a form). The first thing that popped in my mind was the jQuery’s jEditable plugin. I haven’t used it before, and it was the first time I incorporated it to a web application. I was glad that I applied it successfully and it worked smoothly.

So to get things started, you need to include the jQuery script and jEditable plugin in your default layout page. (For me it was the default.ctp ie. app/views/layout/default.ctp)

<?php echo $javascript->link('jquery-1.3.2'); ?>
<?php echo $javascript->link('jquery.jeditable'); ?>

Also add this script on your layout page.

<script>
$(function() {
    $('.edit').editable("http://www.yoursite.com/item/edit", {
         id        : 'data[Module][id]',
         name   : 'data[Module][value]',
         type      : 'text',
         indicator : '<img src="/img/loading.gif">',
         cancel    : 'Cancel',
         submit    : 'Save',
         tooltip   : 'Click to edit'
    });
});
</script>

On your items controller, details function… (ie. app/controller/items_controller.php nothing is new here.)

function details($id=null) {

    $this->Item->recursive = 1;
    $cond = array('Item.id' => $id);
    $this->set('items', $this->paginate('Item', $cond));

}

On your views folder, details page…(ie. app/views/items/details.ctp ) Add a span with the attributes class and id. Make sure that the class name is exactly the same with what you have in the editable js function above. The id should be the item’s ID (note that field name was prefix on the id, for the reason that, it makes the editable function above reusable for any fields on this page.)

<?php 
foreach ($items as $item):
?>
<table >
<tbody>
<tr>
<td >Item Description</td>
<td ><span class="edit" id="description_<?php echo $item['Item']['id']; ?>"><?php echo $item['Item']['description']; ?> </span></td>
</tr>...

On your Items controller page again, edit function… (ie. app/controller/items_controller.php)


function edit($id=null) {

       if ($this->data) {

       uses('sanitize');
       $sanitize= new Sanitize();
       $value = $sanitize->clean($this->data['Module']['value']);
	
       $temp = explode("_",$this->data['Module']['id']);
			
       //this if conditions makes it sure that the field name and id will be split up correctly.
	
       if(count($temp) == '2'){  // ie. itemdescription_1   
		
		// splits field from id
		list($field, $id) = split('_', $this->data['Module']['id']);
	
        }
	if (count($temp) == '3') { // ie. item_description_1		
			
                 $id = $temp[2];
			
			for ($a=0; count($temp)-1>$a; $a++ ){
				$arrtemp[] = $temp[$a];
			}
			$field = implode("_",$arrtemp);
			
	}
	if (count($temp) == '4') { // ie. item_description_category_1 			
			$id = $temp[3];
			
			for ($a=0; count($temp)-1>$a; $a++ ){
				$arrtemp[] = $temp[$a];
			}
			$field = implode("_",$arrtemp);
	}
		
	$this->Item->id = $id;
	$this->Item->saveField($field, $value);
	$this->set('value', $value);
         }
}

on your views, edit.ctp add this… (ie. app/views/items/edit.ctp)

<?php echo $value; ?>

Hope this helps! :)

disclaimer: i’m not a php guru, just a mid level one. Feel free to post comments and suggestions :)

Follow

Get every new post delivered to your Inbox.