﻿(function($){  
	jQuery.fn.datatable = function(newoptions){
		var defaults = {
			limit: 10,
		    limits: [10, 25, 50],
		    page: 1,
		    index: 'id',
		    order: '', 
		    images: '/bin/datatable/icons/',
		    filter: false
		};
		var reset = {
			pager: false,
			removeurl: false,
			loadurl: false,
			saveurl: false,
			columns: false,
			insert: false,
			error: function(error) { alert(error); }
		}
			
	    return this.each(function() {
	    	var table = $(this);  	
	    	
	    	var options = defaults;
			var storedoptions = $.cookie(window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1)+'-'+table.attr('id')+'-options');
	    	if (storedoptions) storedoptions = jQuery.extend(options, JSON.parse(storedoptions));
	    	options = jQuery.extend(options, reset);
	    	options = jQuery.extend(options, newoptions);
	    	
	    	this.refresh = function(quiet) { 
	    		grid.fetch(quiet); 
	    	};
    		this.setFilter = function(key, value) {
    			if (!grid.opts.filter) grid.opts.filter = {};
    			grid.opts.filter[key] = value;
    			grid.fetch();
    		};
    		this.clearFilter = function() {
    			grid.opts.filter = false;
    			grid.fetch();
    		};
    		
	    	var grid = {
	    		editable: false,
	    		searchable: false,
	    		opts: options,
	    		cols: options.columns,
	    		pager: options.pager,
	        	rows: [],
	        	saving: false,
	        	addRows: function(rows) {
	        		var body = $('<tbody></tbody');
	        		if (rows.length > 0) {
	        			jQuery.each(rows, function(ir, row) {
		        			var tr = $('<tr></tr>');
		        			tr.attr('id', 'dt-row-'+row['id']);
		        			jQuery.each(grid.cols, function(ic, col) {
		        				var cell = row['cell'][ic] || '&nbsp;';
		        				
		        				if (col.filemanager && col.filemanager.script && col.filemanager.key) {
        							var q = 'key='+col.filemanager.key;
        							if (col.filemanager.idsub) q = q + '&sub='+row['id'];
        							else if (col.filemanager.sub) q = q + '&sub='+col.filemanager.sub;
        							if (col.filemanager.manage) q = q + '&manage='+col.filemanager.manage;
        							if (col.filemanager.hideext) q = q + '&hideext='+col.filemanager.hideext;
        							if (col.filemanager.css) q = q + '&css='+col.filemanager.css;
        							var d = '';
        							if (col.filemanager.width) d = d + ',width='+col.filemanager.width;
        							if (col.filemanager.height) d = d + ',height='+col.filemanager.height;
	        						var link = $('<a href="javascript: void(0);">'+cell+'</a>');
	        						link.click(function() {
	        							var filemanager = window.open(col.filemanager.script+'?'+q,'Filemanager','location=0,status=0,scrollbars=1'+d);
	        							if (col.filemanager.manage) filemanager.onunload = function() { grid.fetch(); };
	        						});
	        						cell = $('<td></td>');
	        						link.appendTo(cell);
	        					}
	        					else cell = $('<td>'+cell+'</td>');
	        					
		        				if (col.align) cell.css('text-align', col.align);
		        				else cell.css('text-align', 'center');
		        				cell.appendTo(tr);
		        			});
		        			if (grid.editable || grid.opts.removeurl) {
		        				cell = $('<td style="text-align:center"></td>');
			        			if (grid.editable) {
		        					var edit = $('<img src="'+grid.opts.images+'edit.gif" class="dt-button-edit">');
		        					var save = $('<img src="'+grid.opts.images+'save.gif" class="dt-button-save" style="display:none">');
		        					var cancel = $('<img src="'+grid.opts.images+'cancel.gif" class="dt-button-cancel" style="display:none">');
		        				}
		        				if (grid.opts.removeurl) var remove = $('<img src="'+grid.opts.images+'delete.gif" class="dt-button-delete">');
	        					
	        					if (grid.editable) { 
		        					edit.click(function() {
		        						grid.editRow(row['id']);
		        						edit.hide();
		        						remove.hide();
		        						save.show();
		        						cancel.show();
		        					}).appendTo(cell);
		        					save.click(function() {
		        						grid.saveRow(row['id']);
		        					}).appendTo(cell);
		        					cancel.click(function() {
		        						grid.cancelEdit();
		        					}).appendTo(cell);
	        					}
	        					if (grid.opts.removeurl) {
		        					remove.click(function() {
		        						grid.removeRows(row['id'], function() {
		        							return confirm('Are you sure you want to delete this row?');
		        						});
		        					}).appendTo(cell);
		        				}
		        				cell.css('width', 50);
		        				cell.appendTo(tr);
		        			}
		        			tr.find('td:first').append('<input type="hidden" name="id" value="'+row['id']+'">');
							body.append(tr);
	        			});
	        		}
	        		else body.append('<td colspan="'+(grid.cols.length + 1)+'" style="font-weight:bold; text-align:center">No records to view</td>');
	        		body.appendTo(table);
	        		grid.rows = rows;
	        	},
	        	addInsert: function() {
	        		var row = $('<tr></tr>');
        			row.attr('id', 'dt-row-0');
        			jQuery.each(grid.cols, function(ic, col) {
        				var cell = $('<td></td>');
						if (col.editor && col.name) {
							var editor = col.editor;
	        				if (editor.type === 'select') {
	        					var input = $('<select name="'+col.name+'"></select>');
	        					
	        					if (col.align) input.css('text-align', col.align);
	        					else input.css('text-align', 'center');
	        					if (editor.values) {
	        						for(var z in editor.values) {
	        							var option = editor.values[z];
	        							if (option.caption === cell.text()) var selected = option.value;
		        						input.append('<option value="'+option.value+'">'+option.caption+'</option>');
		        					}
	        					}
	        					if (selected) input.val(selected);
	        				}
	        				else if (editor.type === 'textarea') {
	        					var input = $('<textarea name="'+col.name+'"></textarea>');
	        					if (editor.rows) input.attr('rows', editor.rows);
	        					input.text(cell.text());
	        				}
	        				else if (editor.type === 'file') {
	        					var input = $('<input type="file" name="'+col.name+'">');
	        					if (editor.size) input.attr('size', editor.size);
	        				}
	        				else {
	        					var input = $('<input type="text" name="'+col.name+'">');
	        					if (col.align) input.css('text-align', col.align);
	        					else input.css('text-align', 'center');
	        				}
	        				cell.css('text-align', 'center');
        					cell.append(input);
						}
        				cell.appendTo(row);
        			});
        			if (grid.opts.insert) {
        				var actions = $('<td style="text-align:center"></td>');
    					var save = $('<img src="'+grid.opts.images+'save.gif" class="dt-button-save">');					        					
    					save.click(function() {
    						grid.saveRow(0);
    					}).appendTo(actions)
    					actions.appendTo(row);
    				}
        			row.find('input').keydown(function(event) {
	        			if (event.keyCode == 13) row.find('.dt-button-save').click();
	        		});
					row.appendTo(table);
	        	},
	        	addFilter: function() {
	        		if (grid.searchable) {
		        		var row = $('<tr></tr>');
	        			row.attr('id', 'dt-row-search');
	        			jQuery.each(grid.cols, function(ic, col) {
	        				var cell = $('<td></td>');
							if (col.searchable && col.name) {
								var v = grid.opts.filter[col.name] || '';
								cell.append($('<input type="text" name="'+col.name+'" value="'+v+'">'));
							}
	        				if (col.actions) {
	        					var search = $('<img src="'+grid.opts.images+'search.gif" class="dt-button-search">');
	        					var cancel = $('<img src="'+grid.opts.images+'cancel.gif" class="dt-button-cancel">');				        					
	        					search.click(function() {
	        						grid.opts.filter = {};
	        						row.find('input').each(function() {
	        							var inp = $(this);
	        							if (inp.val().length > 0) grid.opts.filter[inp.attr('name')] = inp.val();
	        						});
	        						grid.fetch();
	        					}).appendTo(cell);
	        					cancel.click(function() {
	        						grid.opts.filter = false;
	        						row.remove();
	        						grid.fetch();
	        					}).appendTo(cell);
	        				}
	        				cell.appendTo(row);
	        			});
	        			row.find('input').keydown(function(event) {
		        			if (event.keyCode == 13) row.find('.dt-button-search').click();
		        		});
		        		row.addClass('dt-row dt-filter');
						row.prependTo(table);
					}
	        	},
	        	editRow: function(id) {
	        		var row = table.find('#dt-row-'+id);
	        		table.find('tbody tr').click(function() {
	        			grid.cancelEdit();
	        		})
	        		table.find('.dt-button-edit').unbind('click');
	        		row.unbind('click');
	        		var cells = row.find('td');
	        		
	        		jQuery.each(grid.cols, function(ic, col) {
	        			if (col.editor && col.name) {
	        				var cell = $(cells[ic]);
	        				var editor = col.editor;
	        				if (editor.type === 'select') {
	        					var input = $('<select name="'+col.name+'"></select>');
	        					
	        					if (col.align) input.css('text-align', col.align);
	        					else input.css('text-align', 'center');
	        					if (editor.values) {
	        						jQuery.each(editor.values, function(iv, opt) {
	        							if (opt.caption === cell.text()) var selected = opt.value;
		        						input.append('<option value="'+opt.value+'">'+opt.caption+'</option>');
		        					});
	        					}
	        					if (selected) input.val(selected);
	        				}
	        				else if (editor.type === 'textarea') {
	        					var input = $('<textarea name="'+col.name+'"></textarea>');
	        					if (editor.rows) input.attr('rows', editor.rows);
	        					input.text(cell.text());
	        				}
	        				else if (editor.type === 'file') {
	        					var input = $('<input type="file" name="'+col.name+'">');
	        					if (editor.size) input.attr('size', editor.size);
	        				}
	        				else {
	        					var input = $('<input type="text" name="'+col.name+'">');
	        					if (col.align) input.css('text-align', col.align);
	        					else input.css('text-align', 'center');
	        					input.val(cell.text());
	        				}
        					cell.empty();
        					cell.css('text-align', 'center');
        					cell.append(input);
	        			}
	        		});
	        		row.find('input').keydown(function(event) {
	        			if (event.keyCode == 13) row.find('.dt-button-save').click();
	        		});
	        		$('input:text:first:visible').focus();
	        	},
	        	cancelEdit: function() {
	        		if (!grid.saving || (grid.saving && confirm('Save in progress, are you sure you want to cancel?'))) {
	        			grid.clear();
	        			grid.addRows(grid.rows);
	        			if (grid.opts.insert) grid.addInsert();
	        			grid.color();
	        			if (grid.opts.filter) grid.addFilter();
	        		}
	        	},
	        	saveRow: function(id, callback) {
	        		var row = table.find('#dt-row-'+id);
	        		grid.saving = true;
	        		var tmprow = row.clone();
	        		tmprow.find('.dt-button-edit,.dt-button-cancel,.dt-button-delete').hide();
	        		tmprow.find('.dt-button-save').replaceWith('<img src="'+grid.opts.images+'loading-small.gif">');
	        		tmprow.insertAfter(row);
	        		row.hide();
	        		row.wrap('<form id="dt-form" method="POST" action="'+grid.opts.saveurl+'" enctype="multipart/form-data"></form>');
	        		var form = $('#dt-form');
	        		form.ajaxForm(function() { 
	        			grid.opts.filter = false;
	        			grid.fetch(true); 
	        			grid.saving = false;
	        			form.remove();
	        		});   
	        		form.submit();   		
	        	},
	        	clear: function() {
	        		table.find('tbody').remove();
	        	},
	        	color: function() {
	        		table.find('tbody tr').removeClass().addClass('dt-row');
	        		table.find('tbody tr:odd').addClass('dt-row-alt');
	        		table.find('tbody tr').mouseover(function() {
	        			$(this).addClass('dt-hover');
	        		});
	        		table.find('tbody tr').mouseout(function() {
	        			$(this).removeClass('dt-hover');
	        		});
	        	},
	        	removeRows: function(ids, confirm) {
	        		if (ids.constructor.toString().indexOf("Array") == -1) ids = 'id='+ids;
	        		else ids = $.param(ids);
	        		if (confirm()) {
	        	    	$.ajax({
		        			type: 'POST',
		        			url: grid.opts.removeurl,
		        			dataType: 'json',
		        			data: ids,
		        			success: function(response, status) {
		        				if (response.error) grid.opts.error(response.error);
		        				else grid.fetch(true);
		        			},
		        			error: function(obj, status, error) {
		        				grid.opts.error(status || error);
		        			}
		        		});
	        		}
	        	},
	        	setPager: function() {
	        		if (grid.pager) {
		        		$(grid.pager).find('#dt-pager-first,#dt-pager-prev,#dt-pager-next,#dt-pager-end').hide();
						$(grid.pager).find('#dt-pager-select').empty();
						
						for(x=1;x<=grid.opts.pages;x++) $(grid.pager).find('#dt-pager-select').append('<option value="'+x+'">'+x+'</option>');
						$(grid.pager).find('#dt-pager-select').val(grid.opts.page);
						$(grid.pager).find('#dt-pager-pages').html(' of '+grid.opts.pages);
						
						$(grid.pager).find('#dt-pager-limits').val(grid.opts.limit);
						
						if (grid.opts.records == 0) $(grid.pager).find('#dt-pager-count').text('No records to view');
						else if (grid.opts.records < grid.opts.limit) $(grid.pager).find('#dt-pager-count').text('Records: '+grid.opts.records);
						else {
							if (grid.opts.page == 1) $(grid.pager).find('#dt-pager-next,#dt-pager-end').show();
							else if (grid.opts.page == grid.opts.pages) $(grid.pager).find('#dt-pager-first,#dt-pager-prev').show();
							else $(grid.pager).find('#dt-pager-first,#dt-pager-prev,#dt-pager-next,#dt-pager-end').show();
							$(grid.pager).find('#dt-pager-count').text('Records: '+grid.opts.records);
						}
					}
	        	},
	        	fetch: function(quiet) {
	        		if (grid.opts.loadurl.indexOf('?') > -1) var query = '&page='+grid.opts.page+'&limit='+grid.opts.limit+'&index='+grid.opts.index+'&order='+grid.opts.order
	        		else var query = '?page='+grid.opts.page+'&limit='+grid.opts.limit+'&index='+grid.opts.index+'&order='+grid.opts.order;
	        		if (grid.opts.filter) for(var key in grid.opts.filter) query = query+'&'+key+'='+escape(grid.opts.filter[key]);
	        		if (!quiet) {
	        			grid.clear();
	        			$('<tr><td colspan="'+(grid.cols.length + 1)+'" style="text-align:center"><img src="'+grid.opts.images+'loading.gif"></td></tr>').appendTo(table);
	        		}
	        		$.ajax({
	        			type: 'POST',
	        			url: grid.opts.loadurl+query,
	        			dataType: 'json',
	        			success: function(response, status) {
	        				if (response.error) grid.opts.error(response.error);
	        				else {
	        					grid.opts.page = response.page || 1;
	        					grid.opts.pages = response.pages || 1;
	        					grid.opts.records = response.records || 0;
	        					if (response.rows) {
	        						grid.clear();
	        						grid.addRows(response.rows);
	        						if (grid.opts.insert) grid.addInsert();
	        						grid.color();
	        						if (grid.opts.filter) grid.addFilter();
	        						grid.setPager();
	        					}
	        					$.cookie(window.location.pathname.substring(window.location.pathname.lastIndexOf('/') + 1)+'-'+table.attr('id')+'-options', JSON.stringify(grid.opts));
	        				}
	        			},
	        			error: function(obj, status, error) {
	        				grid.opts.error(status || error);
	        			}
	        		});
	        	}
	        };
	        
	        table.addClass('dt-grid');
	        
	        var header = $('<thead></thead>');
	        row = $('<tr></tr>');
    		jQuery.each(grid.cols, function(ic, col) {
				if (col.editor) grid.editable = true;
				if (col.searchable) grid.searchable = true;
				if (col.sorted) {
					grid.opts.index = col.name;
					grid.opts.order = col.sorted;
				}
				
				var caption = col.caption || '';
    			var cell = $('<td>'+caption+'</td>');
    			if (col.width) cell.css('width', col.width);
    			if (col.sortable) {
    				cell.css('cursor', 'pointer');
    				cell.attr('title', col.name);
	    			cell.mouseover(function() {
	        			$(this).addClass('dt-hover');
	        		});
	        		cell.mouseout(function() {
	        			$(this).removeClass('dt-hover');
	        		});
	        		cell.click(function() {
	        			header.find('.dt-header-sort').remove();
	        			grid.opts.index = $(this).attr('title');
	        			if (grid.opts.order === 'DESC') {
	        				grid.opts.order = '';
	        				$(this).append('<img src="'+grid.opts.images+'sort-asc.png" class="dt-header-sort">');
	        			}
	        			else {
	        				grid.opts.order = 'DESC';
	        				$(this).append('<img src="'+grid.opts.images+'sort-desc.png" class="dt-header-sort">');
	        			}
	        			grid.fetch();
	        		});
	        	}
    			cell.appendTo(row);
    			
    			if (col.editor && col.editor.valueurl) {
    				$.ajax({
	        			type: 'POST',
	        			async: false,
	        			url: col.editor.valueurl,
	        			dataType: 'json',
	        			success: function(response, status) {
	        				if (response.error) grid.opts.error(response.error);
	        				else if (response.options) {
	        					col.editor.values = response.options;
	        				}
	        			},
	        			error: function(obj, status, error) {
	        				grid.opts.error(status || error);
	        			}
	        		});	
    			}
    		});
    		if (grid.editable || grid.opts.removeurl) row.append($('<td>Actions</td>'));
    		row.addClass('dt-header');
    		row.appendTo(header);
    		header.prependTo(table);
   			
   			if (grid.pager) {
	    		grid.pager.attr('id', 'dt-pager');
	    		grid.pager.addClass('dt-pager');
	    		var left = $('<div class="dt-pager-left" style="float: left; width:32%; text-align: left"></div>');		
	    		var mid = $('<div class="dt-pager-mid" style="float: left; width:33%; text-align: center"></div>');
	    		var right = $('<div class="dt-pager-right" style="float: right; width:32%; text-align: right"></div>');
	    		
	    		left.append($('<span class="dt-pager-limits">Show: </span>'));
	    		var limits = $('<select id="dt-pager-limits" class="dt-pager-limits"></select>');
	    		for(var x in grid.opts.limits) {
	    			limits.append('<option value="'+grid.opts.limits[x]+'">'+grid.opts.limits[x]+'</option>');
	    		}
	    		left.append(limits.change(function() {
	    			grid.opts.limit = $(this).val();
	    			grid.fetch();
	    		})); 
	    		left.append($('<span id="dt-pager-count" class="dt-pager-count" style="padding-left:5px">No records to view</span>'));    		
	    		
	    		mid.append($('<img id="dt-pager-first" src="'+grid.opts.images+'seek-first.png">').click(function() {
	    			grid.opts.page = 1;
					grid.fetch();
	    		}));
	    		mid.append($('<img id="dt-pager-prev" src="'+grid.opts.images+'seek-prev.png">').click(function() {
	    			grid.opts.page--;
	    			if (grid.opts.page < 0) grid.opts.page = 0;
					grid.fetch();
	    		}));
	    		mid.append($('<span class="dt-pager-select">Page: </span>'));
	    		mid.append($('<select id="dt-pager-select" class="dt-pager-select"></select>').change(function() {
	    			grid.opts.page = $(this).val();
	    			grid.fetch();
	    		}));
	    		mid.append($('<span id="dt-pager-pages"> of 1</span>'));
	    		
	    		mid.append($('<img id="dt-pager-next" src="'+grid.opts.images+'seek-next.png">').click(function() {
	    			grid.opts.page++;
	    			if (grid.opts.page > grid.opts.pages) grid.opts.page = grid.opts.pages;
					grid.fetch();
	    		}));
	    		mid.append($('<img id="dt-pager-end" src="'+grid.opts.images+'seek-end.png">').click(function() {
	    			grid.opts.page = grid.opts.pages;
					grid.fetch();
	    		}));
	    			
				right.append($('<img id="dt-pager-refresh" src="'+grid.opts.images+'refresh.png">').click(function() {
					grid.fetch();
	    		}));  		
	    		if (grid.searchable) {
		    		right.append($('<img id="dt-pager-search" src="'+grid.opts.images+'search.gif">').click(function() {
		    			grid.addFilter();
		    		}));
		    	}
		    	
	    		grid.pager.append(left);
	    		grid.pager.append(mid);
	    		grid.pager.append(right);
	    		if (jQuery.browser.mozilla) grid.pager.append($('<div style="height: 1px; clear:both;"></div>'));
    		}
    		grid.fetch();
	    });
	};
})(jQuery);

$.fn.extend({
	refresh: function(quiet) {
		return this.each(function() {
			if (this.refresh) this.refresh(quiet);
			else return false;
		});
	},
	setFilter: function(key, value) {
		return this.each(function() {
			if (this.setFilter) this.setFilter(key, value);
			else return false;
		});
	},
	clearFilter: function() {
		return this.each(function() {
			if (this.clearFilter) this.clearFilter();
			else return false;
		});
	}
});