/*==============================================================================
2011Apr16 - added flos.makeNav() based on "Simple Stupid jQuery Accordian"
2011Mar12 - added Paul Irish's improved console.log()
2010Dec10 - sdded jQuery HTML5 placeholder fix.js from gist.github
2010Dec10 - added flos.getArgs() - 'JavaScript, definitive guide' p.272
2010Dec08 - moved no longer used material to 'legacy.js'
2010Dec06 - added Manifest event handlers - 'BLOG of Ben Nadel' 8Oct2010
2009Sep24 - added dms2deg function
2009Sep22 - added deg2dms function
2009Feb13 - added deg2rad function
2008Aug19 - modified further to work with the 'jQuery' library instead
2008Aug04 - modified from older jsLib.js to work with the 'dojo' library
==============================================================================*/
var FALSE = false;
var TRUE = true;

var oneMinute= 60 * 1000;  // milliseconds in a minute
var oneHour= oneMinute * 60;
var oneDay= oneHour * 24;
var oneWeek= oneDay * 7;

// usage: log('inside coolFunc', this, arguments);
// paulirish.com/2009/log-a-lightweight-wrapper-for-consolelog/
window.log = function(){
  log.history = log.history || [];   // store logs to an array for reference
  log.history.push(arguments);
  arguments.callee = arguments.callee.caller; 
  if(this.console) console.log( Array.prototype.slice.call(arguments) );
};
// make it safe to use console.log always
(function(b){function c(){}for(var d="assert,count,debug,dir,dirxml,error,exception,group,groupCollapsed,groupEnd,info, log,markTimeline,profile,profileEnd,time,timeEnd,trace,warn".split(","),a;a=d.pop();)b[a]=b[a]||c})(window.console=window.console||{});

		// --- 
		$('[placeholder]').focus(function() {
		  var input = $(this);
		  if (input.val() == input.attr('placeholder')) {
				input.val('');
				input.removeClass('placeholder');
			}
		}).blur(function() {
		  var input = $(this);
		  if (input.val() == '' || input.val() == input.attr('placeholder')) {
		    input.addClass('placeholder');
		    input.val(input.attr('placeholder'));
		  }
		}).blur().parents('form').submit(function() {
		  $(this).find('[placeholder]').each(function() {
		    var input = $(this);
		    if (input.val() == input.attr('placeholder')) {
		      input.val('');
		    }
		  })
		});
		
		
// some additions to the jQuery base (plugins??)

// Monitor Manifest Activity - 'BLOG of Ben Nadel' 8Oct2010 - fl
(function($){
  $.monitorManifest = function(whereId) {

  	var manFile = $('html').attr('manifest');

		// Get the DOM references we'll need to play with.
		// you have to create 'container' elements in your app for  each of these
		var appStatus = $( "#applicationStatus" );
		var appEvents = $( "#applicationEvents" );
		var cacheProgress = $( "#cacheProgress" );
		
		var fileArray = [];
		var appCache = window.applicationCache;
  		
 		// Create a cache properties object to help us keep track of
		// the progress of the caching.
		var cacheProperties = {
			filesDownloaded: 0,
			totalFiles: 0
		};
    
		// I log an event to the event list.
		function logEvent( event ){
			appEvents.append(
				"<li>" +(event + " ... " + (new Date()).toTimeString()) + "</li>"
			);
		};
  
 		// I get the total number of files in the cache manifest.
 		// I do this by manually parsing the manifest file.
		function getTotalFiles(){
			// First, reset the total file count and download count.
			cacheProperties.filesDownloaded = 0;
			cacheProperties.totalFiles = 0;
  
			// Now, grab the cache manifest file.
			$.ajax({
				type: "get",
				url: manFile,
				dataType: "text",
				cache: false,
				error: function(content){
					var errTxt = "Unable to access manifest file: '"+manFile+"'";
					$('#cacheProgress').html('<span class="error">'+errTxt+'</span>');
					console.log(errTxt);
				},
				success: function( content ){
					// Strip out the non-cache sections.
					content = content.replace(
						new RegExp("(NETWORK|FALLBACK):((?!(NETWORK|FALLBACK|CACHE):)[\\w\\W]*)", "gi"),
						""
					);
 	 
					// Strip out all comments.
					content = content.replace(
						new RegExp( "#[^\\r\\n]*(\\r\\n?|\\n)", "g" ),
						""
					);
 	 
					// Strip out the cache manifest header and
					// trailing slashes.
					content = content.replace(
						new RegExp( "CACHE MANIFEST\\s*|\\s*$", "g" ),
						""
					);
 	 
					// Strip out extra line breaks and replace with
					// a hash sign that we can break on.
					content = content.replace(
						new RegExp( "[\\r\\n]+", "g" ),
						"#"
					);
  
					// Get the total number of files.
					fileArray = content.split( "#" );
					var totalFiles = fileArray.length;
					//console.log(fileArray);					
 	 
					// Store the total number of files. Here, we are
					// adding one for *THIS* file, which is cached
					// implicitly as it points to the manifest.
					cacheProperties.totalFiles = (totalFiles);
				}
			});
		};
  
		function displayProgress(){
			// Increment the running total.
			cacheProperties.filesDownloaded++;
			var n = cacheProperties.filesDownloaded;
			var txt = '';
  
			// Check to see if we have a total number of files.
			if (cacheProperties.totalFiles){
  
				// We have the total number of files, so output the
				// running total as a function of the known total.
				txt = 
					"application file: " + "( #"+ cacheProperties.filesDownloaded + 
					" of " + cacheProperties.totalFiles + "): "+
					fileArray[n-1] + " downloaded.";
			} else {
				// We don't yet know the total number of files, so
				// just output the running total.
				txt = 
					"file #"+	cacheProperties.filesDownloaded +": "+
					fileArray[n-1] + " downloaded.";
			}
			cacheProgress.text(txt);
			appEvents.append("<li>" +txt+ "</li>");
		};

		// Bind the manual update link.
		$("#manifestUpdate").bind('click',null,function( event ){
				//console.log('checking for manifest update');
				// Prevent the default event.
				event.preventDefault();
 
				// Manually ask the cache to update.
				appCache.update();
			}
		);
  
		$( window.applicationCache ).bind("checking",function( event ){
	 		appEvents.html('');
	 		logEvent( "Checking for manifest" );
	 		appEvents.html('');
		});
  
 		$( window.applicationCache ).bind("noupdate",function( event ){
 			logEvent( "No cache updates" );
 		});
  
 		$( window.applicationCache ).bind("downloading",function( event ){
  	// create places on page for various outputs
  	var where = $('#'+whereId);
  		where.hide();
  		where.html('<p><a id="manifestUpdate" href="#">Check for an updated Cache</a></p>');
			where.append('<h2>Application Cache Events</h2>');
			where.append('<p>Progress: <span id="cacheProgress">N/A</span></p>');
			where.append('<ul id="applicationEvents"></ul-->');
 			where.show();
 			
 			logEvent( "Downloading cache" );
 			getTotalFiles();
 		});
  
 		$( window.applicationCache ).bind("progress",function( event ){
 			//logEvent( "File downloaded" );
 			displayProgress();
		});
  
 		$( window.applicationCache ).bind("cached",function( event ){
 			logEvent( "All files downloaded" );
 		});
  
 		$( window.applicationCache ).bind("updateready",function( event ){
 			logEvent( "New cache available, swapping now!" );
 			window.applicationCache.swapCache();
 		});
  
 		$( window.applicationCache ).bind("obsolete",function( event ){
 			logEvent( "Manifest cannot be found" );
 		});
  
 		$( window.applicationCache ).bind("error",function( event ){
			var str = "There are "+arguments.length+" arguments:\n";
			for (var key in event)
				str += key+":"+event[key]+"\n";
		 	logEvent( "An error occurred:\n"+str );
 		});
	}
})(jQuery);

// set ReadOnly - 'jQuery in Action',p201 25Aug2008 - fl
(function($){
  $.fn.setReadOnly = function(readonly) {
    return this.filter('input:text')
      .attr('readonly',readonly)
      .css('opacity', readonly ? 0.5 : 1.0);
  }
})(jQuery);

// date formatter - 'jQuery in Action, 2ed',p212 18Nov2010 - fl
(function($){
  $.formatDate = function(date,pattern) {
    var result = [];
    while (pattern.length>0) {
      $.formatDate.patternParts.lastIndex = 0;
      var matched = $.formatDate.patternParts.exec(pattern);
      if (matched) {
        result.push($.formatDate.patternValue[matched[0]].call(this,date));
        pattern = pattern.slice(matched[0].length);
      }
      else {
        result.push(pattern.charAt(0));
        pattern = pattern.slice(1);
      }
    }
    return result.join('');
  };

  $.formatDate.patternParts =
    /^(yy(yy)?|M(M(M(M)?)?)?|d(d)?|EEE(E)?|a|H(H)?|h(h)?|m(m)?|s(s)?|S)/;

  $.formatDate.monthNames = [
    'January','February','March','April','May','June','July',
    'August','September','October','November','December'
  ];

  $.formatDate.dayNames = [
    'Sunday','Monday','Tuesday','Wednesday','Thursday','Friday',
    'Saturday'
  ];

  $.formatDate.patternValue = {
    yy: function(date) {
      return $.toFixedWidth(date.getFullYear(),2);
    },
    yyyy: function(date) {
      return date.getFullYear().toString();
    },
    MMMM: function(date) {
      return $.formatDate.monthNames[date.getMonth()];
    },
    MMM: function(date) {
      return $.formatDate.monthNames[date.getMonth()].substr(0,3);
    },
    MM: function(date) {
      return $.toFixedWidth(date.getMonth()+1,2);
    },
    M: function(date) {
      return date.getMonth()+1;
    },
    dd: function(date) {
      return $.toFixedWidth(date.getDate(),2);
    },
    d: function(date) {
      return date.getDate();
    },
    EEEE: function(date) {
      return $.formatDate.dayNames[date.getDay()];
    },
    EEE: function(date) {
      return $.formatDate.dayNames[date.getDay()].substr(0,3);
    },
    HH: function(date) {
      return $.toFixedWidth(date.getHours(),2);
    },
    H: function(date) {
      return date.getHours();
    },
    hh: function(date) {
      var hours = date.getHours();
      return $.toFixedWidth(hours>12 ? hours - 12 : hours,2);
    },
    h: function(date) {
      return date.getHours()%12;
    },
    mm: function(date) {
      return $.toFixedWidth(date.getMinutes(),2);
    },
    m: function(date) {
      return date.getMinutes();
    },
    ss: function(date) {
      return $.toFixedWidth(date.getSeconds(),2);
    },
    s: function(date) {
      return date.getSeconds();
    },
    S: function(date) {
      return $.toFixedWidth(date.getMilliseconds(),3);
    },
    a: function(date) {
      return date.getHours() < 12 ? 'AM' : 'PM';
    }
  };

  $.toFixedWidth = function(value,length,fill) {
    if (!fill) fill = '0';
    var result = value.toString();
    var padding = length - result.length;
    if (padding < 0) {
      result = result.substr(-padding);
    }
    else {
      for (var n = 0; n < padding; n++) result = fill + result;
    }
    return result;
  };
})(jQuery);

// numbers to fixed width - 'jQuery in Action',p194 25Aug2008 - fl
(function($){
	$.toFixedWidth = function(value, length, fill) {
		var result = value.toString();
		if (!fill) fill = '0';
		var padding = length - result.length;
		if (padding < 0) {
			result = result.substr(-padding);
		}
		else {
			for (var n=0; n<padding; n++) result = fill+result;
		}
		return result;
	};
})(jQuery);

// table stripe - 'Learning jQuery 1.3', p.183 11Dec2010 - fl
// -- should be called as $('tbody.striped').stripe();
$.fn.stripe = function () {
	return this.find('tr:visible:even').removeClass('odd').addClass('even')
						 .end()
						 .find('tr:visible:odd').removeClass('even').addClass('odd');
}

// element enable/disable - 'jQuery in Action' 22Aug2008 - fl
$.fn.disable = function () {
	return this.each(function () {
					if (typeof this.disabled != "undefined)") this.disabled = true;
				 });
}
$.fn.enable = function () {
	return this.each(function () {
					if (typeof this.disabled != "undefined)") this.disabled = false;
				 });
}

/* --------------------------------- */
/* --------------------------------- */
/* --------------------------------- */

var flos = {
makeNav: function () {
	// based on "Stupid Simple jQuery Accordian" by Ryan Stemkoski, 2009
	$(".navHeading").bind('click',null,function() {
		$(".navSelected").removeClass("navSelected").addClass("navUnselected")
		$(this).removeClass("navUnselected").addClass("navSelected");
		$(".navContent").slideUp();	
		$(this).next(".navContent").slideDown();
	});
	
	$(".navContent").hide();
	$(".navHeading").addClass("navUnselected");
	$("nav #defaultOpen").trigger("click");
},

/* --------------------------------- */
getArgs: function () {
	// parses current page's URL following the '?' and
	// returns {'arg1name':arg1val, 'arg2name':arg2val,....}
	var args = new Object(),
			query = location.search.substring(1),
			pairs = query.split('&');
	
	for (var i=0; i<pairs.length; i++) {
		var pos = pairs[i].indexOf('=');
		if (pos == -1) continue;
		var argname = pairs[i].substring(0,pos);
		var value = pairs[i].substring(pos+1);
		value = decodeURIComponent(value);
		args[argname] = value;
	}
	return args; 
},

/* --------------------------------- */
dms2deg: function (inDeg,inMin,inSec) {
	  var deg = parseInt(inDeg);
	  if (isNaN(deg)) deg = 0;
		var min = parseFloat(inMin);
	  if (isNaN(min)) min = 0;
		var sec = parseFloat(inSec);
	  if (isNaN(sec)) sec = 0;
		//console.log("In: deg="+inDeg+"; min="+inMin+"; Out: deg="+deg+", min="+min);
		return (deg+((min+(sec/60.0))/60.0)).toFixed(5);
},
	
/* --------------------------------- */
deg2dms: function (deg) {
	if (deg < 1.0) {
		deg = deg * (-1.0);
		dir = ['S','E'];
	}
	else {
		dir = ['N','W'];
	}
	var iDeg = parseInt(deg);
	var fDeg = deg - iDeg;
	//console.log('deg='+deg+'; int='+iDeg+' frac='+fDeg);
	var min = fDeg * 60.0;
	var iMin = parseInt(min);
	var fMin = min - iMin;
	//console.log('min='+min+'; int='+iMin+' frac='+fMin);
	var sec = fMin * 60.0;
	var iSec = parseInt(sec);
	//console.log('sec='+sec+'; int='+iSec);
	return {'d':iDeg, 'm':iMin, 's':iSec, 'dd':deg, 'dm':min, 'ds':sec, 'dir':dir};
},

/* --------------------------------- */
deg2rad: function (deg) {
		return deg * Math.PI/180.0;
},

/* --------------------------------- */
doNothing: function () {
	//used with setTimeout to give a delay
},

/* --------------------------------- */
dateDiff: function  (dateOlder, dateNewer) {
	//inputs espected to be in form 'yy-mm-dd'
	//alert('older='+dateOlder+'; newer='+dateNewer);
	var date1 = dateOlder.split('-'); if (date1[0]<2000)date1[0] = 20+date1[0];
	var date2 = dateNewer.split('-'); if (date2[0]<2000)date2[0] = 20+date2[0];
	//alert('date='+dateOlder+'; yr='+date1[0]+'; mon='+date1[1]+'; day='+date1[2]+'\n'+
	//	'date='+dateNewer+'; yr='+date2[0]+'; mon='+date2[1]+'; day='+date2[2]);
	var date1Str = new Date(date1[0],date1[1],date1[2]); var date1MS = date1Str.getTime();
	var date2Str = new Date(date2[0],date2[1],date2[2]); var date2MS = date2Str.getTime();
	var diffMS = date2MS-date1MS;
	var diffDays = diffMS/oneDay;
	//alert(' oldest date='+dateOlder+'('+date1MS+')\n newest date='+dateNewer+'('+date2MS+')\n diff='+diffDays+'('+diffMS+')');
	return Math.floor(diffDays);
},

/* --------------------------------- */
thisYr: function (){
	var theDate = new Date();
	return theDate.getFullYear();
},

/* --------------------------------- */
today: function (){
	var theDate = new Date();
	var theYear = theDate.getFullYear();
	var theMonth= theDate.getMonth();
	var theDay  = theDate.getDate();
	return theYear+'-'+theMonth+'-'+theDay;
},

/* --------------------------------- */
fmtDate: function (aDate) {
	if(aDate == null) return '';
	var parts = aDate.split('/');
	var mm = parts[0];
	var dd = parts[1];
	var yy = parts[2];
	return yy+'-'+mm+'-'+dd;
},	

/* --------------------------------- */
unfmtDate: function (aDate) {
	if(aDate == null) return '';
	aDate = (aDate.split(' '))[0];
	var parts = aDate.split('-');
	var yy = parts[0];
	var mm = parts[1];
	var dd = parts[2];
	return mm+'/'+dd+'/'+yy;
},	

/* --------------------------------- */
	roundF2: function ( theVal) {
		return parseFloat((Math.round(theVal * 100.0)) / 100.0);
	},

/* --------------------------------- */
	calcAcres: function  () {
		var theForm = document.lotForm;
		if (theForm.acres.value == 0) {
			theForm.acres.value = theForm.frontage.value * theForm.depth.value;
			theForm.acres.value = (Math.round(theForm.acres.value / 435.60))/100.0;
		}
	},

/* --------------------------------- */
	setYesNo: function (grp,val) {
		if (val == 'y')
		   eval(grp+'_y').checked = true;
		else
		   eval(grp+'_n').checked = true;
	},

/* --------------------------------- */
	changeBoxes: function (action, theForm) {
		//Taken from pp 279-281 of "Begining JavaScrip with DOM Scripting and AJAX" by C.Heilmann
		// 
		var elms = theForm.elements;
		for (var i=0; i<elms.length; i++) {
			if (elms[i].type != 'checkbox') {continue; }
			if (action < 0) {
				elms[i].checked = elms[i].checked ? false : true;
			} else {
				elms[i].checked = action ==1 ? false : true;
			}
		}
	}

};	

