// start base1.js

function isDefined(thevar){
   return (typeof(thevar) == 'undefined') ? false : true;
}

function isExisting(obj){
  return typeof(obj)!='undefined';
}

function is_array(input){
  return typeof(input)=='object'&&(input instanceof Array);
}

function in_array(needle, haystack) {
  var length = haystack.length;
  for(var i = 0; i < length; i++) {
      if(haystack[i] == needle) return true;
  }
  return false;
}

function debug(str) {
  // $debug  = $('#debug');
	// if(!str) return;
	// var date_str = new Date().getTime() + " :";
	// $debug.append(date_str + str + '<br>');
  log(str);
  return;
  
  $.log(str);
  console.log(str);
  //alert(str);
}
      
function log() {
  if(arguments.length > 0) { 
    // join for graceful degregation         
    var args = (arguments.length > 1) ? Array.prototype.join.call(arguments, " ") : arguments[0];          
    
    // this is the standard; firebug and newer webkit browsers support this        
    try {
      console.log(args);
      return true;
    } catch(e) {
      // newer opera browsers support posting erros to their consoles 
      try {
        opera.postError(args);
        return true;
      } catch(e) { }
    } 

    // catch all; a good old alert box         
    alert(args);
    return false;
  }
} 

  
// following 2 from http://www.andrewpeace.com/javascript-is-int.html
function is_int(input) {
  return typeof(input)=='number'&&parseInt(input)==input;
}

// takes a jquery object, splits id, returns 2nd part
// so foo_233 returns 233
function get_target_id($target) {
  var tid = $target.attr("id");
  var ar = tid.split("_");
  return ar[1];
}
                  
function form_input_is_int(input) {
  return !isNaN(input)&&parseInt(input)==input;
}

// removes empty elements from form before submitting (makes for cleaner query string.)
function cleanEmptyFields(theform) {
	//return;
  //var theform = thebutton.form;
	//return true;		
	var fs='';
	for(i=0; i<theform.elements.length; i++) {
		var fldName = theform.elements[i].name;
		//alert(fldName + " = " + theform.elements[i].value); 
		if(theform.elements[i].value == '') theform.elements[i].disabled = true; 
	}
	return true;		
}

function hideEl(el){
	//return;
	if (document.getElementById(el)){
        document.getElementById(el).style.display = 'none';
  } else {
    //alert('hideEl: no element'+el);
  }
}

function showEl(el){
  //alert('showEl:'+el);
  if (document.getElementById(el)){
      document.getElementById(el).style.display = 'block';
  } else {
    alert('showEl: no element'+el);                              
  }
}

// limits input to text field and show # characters left
function limitText(limitField, limitCount, limitNum) {
  var $limitField = $('#'+limitField);
  var $limitCount = $('#'+limitCount);
  if ($limitField.val().length > limitNum) {
		$limitField.val($limitField.val().substring(0, limitNum));
	} else {
		$limitCount.html(limitNum - $limitField.val().length);
	}
}

function autocomplete_off(el_id) { // hack since autocomplete='off' is not strict (x)html
  if(el = document.getElementById(el_id)) el.setAttribute("autocomplete", "off");
}

/**
 * Function : dump()
 * Arguments: The data - array,hash(associative array),object
 *    The level - OPTIONAL
 * Returns  : The textual representation of the array.
 * This function was inspired by the print_r function of PHP.
 * This will accept some data as the argument and return a
 * text that will be a more readable version of the
 * array/hash/object that is given.
 * Docs: http://www.openjs.com/scripts/others/dump_function_php_print_r.php
 */
function dump(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;
	
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}


// Numeric helpers 
// like toFixed (but w/o IE problem where 0.9 becomes 0 and with proper rounding)
// if integer, returns integer (thus 4.00 => 4)
function toFixedCond(value, precision) {
  var dec=parseFloat(value) - parseInt(value);
  if(!dec) return parseInt(value);
  else return toFixedUncond(value, precision);
}

function toFixedUncond(value, precision) {
  var power = Math.pow(10, precision || 0);
  var result = Math.round(value * power) / power; // round to given precision  
  return result.toFixed(precision); 
}

// if any form field changes, uses will be warned if trying to leave the page
var needToConfirm = false;
var formChangedFlag = false; 
window.onbeforeunload = confirmExit;

function confirmExit() {
  if (!needToConfirm || !formChangedFlag) return;
  return "You have attempted to leave this page. If you have made any changes to the fields without Saving, your changes will be lost. Are you sure you want to exit this page?";
}

function d2h(d) {return d.toString(16);} // dec 2 hex
function h2d(h) {return parseInt(h,16);} // hex 2 dec

function color_brightness(hexcolor) {
  var rgb = color_rgb(hexcolor);
  //alert("rgb for " + hexcolor + " = " + rgb.r + '/' + rgb.g + '/' + rgb.b + ' = ' + (rgb.r+ rgb.g + rgb.b) / 765);
  return (rgb.r+ rgb.g + rgb.b) / 765;
}

// returns decimal RGB values from hex color (FFF or FFFFFF)
function color_rgb(hexcolor) {
  var rgb = new Object;
  if(hexcolor.length == 3) {
    rgb.r = h2d(hexcolor.charAt(0)) ^ 2;
    rgb.g = h2d(hexcolor.charAt(1)) ^ 2;
    rgb.b = h2d(hexcolor.charAt(2)) ^ 2;
  } else if(hexcolor.length == 6) {
    rgb.r = h2d(hexcolor.charAt(0) + '' + hexcolor.charAt(1));
    rgb.g = h2d(hexcolor.charAt(2) + '' + hexcolor.charAt(3));
    rgb.b = h2d(hexcolor.charAt(4) + '' + hexcolor.charAt(5));
    //alert(hexcolor.charAt(0) + '' + hexcolor.charAt(1) + ' => ' + h2d(hexcolor.charAt(0) + '' + hexcolor.charAt(1)));
  }
  
  return rgb;
}

// takes a string (from jquery's $el.css('color') like "rgb(20,40,50) and returns hex value (w/o #)
function rgb2hex(rgb) {
  if (rgb.search("rgb") == -1 ) {
    return rgb;
  } else {
    rgb = rgb.match(/^rgba?\((\d+),\s*(\d+),\s*(\d+)(?:,\s*(\d+))?\)$/);
    function hex(x) {
      return ("0" + parseInt(x).toString(16)).slice(-2);
    }
    //return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); 
    return hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]); 
 }
}

//returns true is it is an array
function isArray(obj) {
  return (obj.constructor.toString().indexOf("Array") == -1) ? false : true;
}

// Prototypes

// Array Remove - By John Resig (MIT Licensed)
// Array.prototype.removeEl = function(from, to) {
//   if(!isArray(this)) return;
//   var rest = this.slice((to || from) + 1 || this.length);
//   this.length = from < 0 ? this.length + from : from;
//   return this.push.apply(this, rest);
// };

// try as a normal function
//function removeArrayElement(array, from, to) {
//  var rest = array.slice((to || from) + 1 || array.length);
//  array.length = from < 0 ? array.length + from : from;
//  return array.push.apply(array, rest);
//};

String.prototype.toCamel = function(){
	return this.replace(/(\-[a-z])/g, function($1){return $1.toUpperCase().replace('-','');});
};

String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
}
String.prototype.ltrim = function() {
	return this.replace(/^\s+/,"");
}
String.prototype.rtrim = function() {
	return this.replace(/\s+$/,"");
}

String.prototype.ucfirst = function(){
  return this.charAt(0).toUpperCase() + this.slice(1);
};


String.prototype.capitalize = function(){
  return this.replace(/\S+/g, function(a){
      return a.charAt(0).toUpperCase() + a.slice(1).toLowerCase();
  });
};

function isEmail(em) {
   if(em.length < 6  || em.indexOf('@')<1 || em.indexOf('.') < 1) {
      alert(em + " " + error_not_valid_email);
      return false;
   }
   var validchars = 'abcdefghijklmnopqrstuvwxyz0123456789@.-_';
   for (var i=0; i < em.length; i++) {
      var letter = em.charAt(i).toLowerCase();
      if (validchars.indexOf(letter) != -1)
         continue;
      alert(error_invalid_character + ": " + letter + " " + error_in_email_address);
      return false;
   }
   return true;
}

/*
JSTarget function by Roger Johansson, www.456bereastreet.com
http://www.456bereastreet.com/archive/200610/opening_new_windows_with_javascript_version_12/
*/
var JSTarget = {
init: function(att,val,warning) {
if(!text_new_window) var text_new_window = '(Opens in new window)';
if (document.getElementById && document.createElement && document.appendChild) {
var strAtt = ((typeof att == 'undefined') || (att == null)) ? 'class' : att;
var strVal = ((typeof val == 'undefined') || (val == null)) ? 'non-html' : val;
var strWarning = ((typeof warning == 'undefined') || (warning == null)) ? ' ('+ text_new_window +')' : warning;
var oWarning;
var arrLinks = document.getElementsByTagName('a');
var oLink;
var oRegExp = new RegExp("(^|\\s)" + strVal + "(\\s|$)");
for (var i = 0; i < arrLinks.length; i++) {
oLink = arrLinks[i];
if ((strAtt == 'class') && (oRegExp.test(oLink.className)) || (oRegExp.test(oLink.getAttribute(strAtt)))) {
oWarning = document.createElement("em");
oWarning.appendChild( document.createTextNode(strWarning) );
oLink.appendChild(oWarning);
oLink.onclick = JSTarget.openWin;
}
oWarning = null;
}
}
},
openWin: function(e) {
var event = (!e) ? window.event : e;
if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return true;
else {
var oWin = window.open(this.getAttribute('href'), '_blank');
if (oWin) {
if (oWin.focus) oWin.focus();
return false;
}
oWin = null;
return true;
}
},
/*
addEvent function from http://www.quirksmode.org/blog/archives/2005/10/_and_the_winner_1.html
*/
addEvent: function(obj, type, fn) {
if (obj.addEventListener)
obj.addEventListener(type, fn, false);
else if (obj.attachEvent) {
obj["e"+type+fn] = fn;
obj[type+fn] = function() {obj["e"+type+fn]( window.event );}
obj.attachEvent("on"+type, obj[type+fn]);
}
}
};

// end JS Target
// end base1.js

// start app.js

function search_submit() { 
  var searchForm = $('#advanced_search_form');
  for (var i = 0; i < searchForm.length; i++) {
    var sel_field;
    var search_field;
    var iname = searchForm[i].name;
    var itype  = searchForm[i].type;
    var ivalue = searchForm[i].value;      

    if(iname.indexOf('_select_')==0 && ivalue) {
      fld = iname.substr(8);
      searchfld = document.getElementById('_search_'  +fld);
      searchfld.name = '_search_' + ivalue; // set/update name of search field
    }

    if((itype!= 'submit' && itype != 'hidden') || ivalue=='' || iname=='search') { // remove all fields except add/delete buttons and hidden fields
      searchForm[i].disabled=true;
    }
          
  }

  return true;

}


// converts search operator + value1, value2 into search terms to text used in GET or POST field to search recordset
// also; enables disabled inputs based on value of preceeding inputs
function search2text(fld) { 
  var searchForm = $('#advanced_search_form');
  var field_el    = document.getElementById('_select_'  +fld);
  var operator_el = document.getElementById('_op_'  +fld);
  var value1_el   = document.getElementById('_val1_'+fld);
  var value2_el   = document.getElementById('_val2_'+fld);  

  var field    = field_el.value;
  var operator = operator_el.value;
  var value1   = value1_el.value;
  var value2   = value2_el ? value2_el.value : '';

  //alert("fld=" + fld + " op=" + operator + " val1=" +value1 + " val2=" + value2);  

  // calculate result
  if(!field || !operator) {
    result = '';
  } else if(operator == '=') {
    result = value1;
  } else if(operator == '><') {
    result =  value2 != '' ? operator + value1 + ',' + value2 : '';
  } else if(!value1) {
    result = '';
  } else {
    var result = operator + value1;
  } 

  
  // enable/disable inputs
  operator_el.disabled = field ? false : true;
  value1_el.disabled = operator && !operator_el.disabled ? false : true; 
  value2_el.disabled = operator == '><' && value1 && !value1_el.disabled ? false : true; 
  if(operator == '><' && value1 !='' && value2 !='' && value2 < value1) {
    result = '';
    alert("Value 2 must be greater than or equal to value1");
  }
  if(fld=='_new_') $('#_show_search').attr("disabled", (result ? false : true)); 

  // set the result field
  $('#_adv_search_'+fld).val(result); 
  
  alert("search2text: " + '#_adv_search_'+fld + "=" + result + " now:" + $('#_adv_search_'+fld).val());

}

// takes a set of checkboxes (with same name)
// writes separated list of values if checked to result_id
function checkboxes2string(parent_id, result_id) {
  var checkArray = new Array();
  var checkboxes_on = $('#' + parent_id + ' input:checked');
  for (var i = 0; i < checkboxes_on.length; i++) checkArray.push(checkboxes_on[i].value);
  $('#' + result_id).val(checkArray.join(','));
}

// takes a set of checkboxes (with same name)
// writes separated list of values if checked to result_id
function checkboxes2flags(parent_id, result_id) {
  var checkboxes_on = $('#' + parent_id + ' input:checked');
  var result = 0;
  for (var i = 0; i < checkboxes_on.length; i++) result |= checkboxes_on[i].value;
  $('#' + result_id).val(result);
}

// disabled all empty fields in a form
function cleanSearch(obj) {
  //obj.parent.disabled=true;
  //obj.ref_link.disabled=true;
  //obj.ref_name.disabled=true;
  for (var i = 0; i < obj.length; i++) {
    var iname = obj[i].name;
    var ivalue = obj[i].value;
    if(ivalue == '') obj[i].disabled=true;    
    if(iname.indexOf('__comp__')>-1 && ivalue=='') { // this is an empty comparison operator - disable
      obj[i].disabled=true;
    }
  }
  return true;
}

// end app.js

// start datetime.js 

// date/time helpers 
function add_days(start_date, num_days) {
  var sd = new Date(start_date.getTime() + num_days * 1000 * 3600 * 24);
  return sd;
}

function add_hours(start_date, num_hours) {
  var sd = new Date(start_date.getTime() + num_hours * 1000 * 3600);
  return sd;
}

// returns Thursay September 24, 2009
function sql2human(dateStr) {
  if(!dateStr) return 'N/A';
  var date = sql2date(dateStr);
  return date.toLocaleDateString();
}

// returns 24 Sep 2009
function sql2human_short(dateStr) {
  if(!dateStr) return 'N/A';
  var date = sql2date(dateStr);
  return date.getDate() + " " + monthNamesShort[date.getMonth()] + " " + date.getFullYear();
}

// returns 24 Sep
function sql2human_shortest(dateStr) {
  if(!dateStr) return 'N/A';
  var date = sql2date(dateStr);
  return date.getDate() + " " + monthNamesShort[date.getMonth()];
}

// returns Thu 24 Sep 2009
function sql2human_short_day(dateStr) {
  if(!dateStr) return 'N/A';
  var date = sql2date(dateStr);
  return dayNamesShort[date.getDay()] + " " + date.getDate() + " " + monthNamesShort[date.getMonth()] + " " + date.getFullYear();
}

// returns Thu 24 Sep 10:30
function sql2human_short_day_time(dateStr) {
  if(!dateStr) return 'N/A';
  var date = sql2date(dateStr);
  var date_str = dayNamesShort[date.getDay()] + " " + date.getDate() + " " + monthNamesShort[date.getMonth()];
  if(strip_date(dateStr) && strip_date(dateStr) != '00:00:00') date_str = date_str + ' ' + zero_pad(date.getHours()) + ":" + zero_pad(date.getMinutes());
  return date_str;
}

// returns 10:30
function sql2human_short_time(dateStr) {
  if(!dateStr) return 'N/A';
  var date = sql2date(dateStr);
  return zero_pad(date.getHours()) + ":" + zero_pad(date.getMinutes());
}

// prepends zero to day/month/hour/minute if < 10
function zero_pad(val) {
  var str = val.toString();
  return str.length < 2 ? '0' + str : str;
}

// by kj
function fixDate(dateStr) {
  if(!dateStr) return;
  var datePat = /^(\d{4})(\/|-)(\d{1,2})(\/|-)(\d{1,2})$/;
  var matchArray = dateStr.match(datePat); // is the format ok?
  year = matchArray[1]; // p@rse date into variables
  month = matchArray[3];
  day = matchArray[5];
  if(day.length<2)
     day = "0" + day;
  if(month.length<2)
     month = "0" + month;
  return year + "-" + month + "-" + day;
}

function sql2ymd(inputDate) {
  var dateTimeArray = inputDate.split(' ');
  var dateString = dateTimeArray[0]
  var pattern = /(^\d{4})-(\d{2})-(\d{2}$)/
  var result = dateString.match(pattern);
  return {y: result[1], m: result[2], d: result[3]}
}

function sql2date(inputDate) {
  if(!inputDate) return '<NAD>';
  // mysql date time as YYYY-MM-DD hh:mm:ss
  var dateTimeArray = inputDate.split(' ');
  var dateString = dateTimeArray[0]
  var timeString = dateTimeArray[1]

  // parse the date from YYYY-MM-DD
  var pattern = /(^\d{4})-(\d{2})-(\d{2}$)/
  var result = dateString.match(pattern);

  var year = result[1];
  var month = result[2];
  var day = result[3];
    
  var date = new Date(year, month - 1, day, 0, 0, 0)
  
  if(timeString) {
    // now parse the time from HH:MM:SS
    pattern = /(^\d{2}):(\d{2}):(\d{2})/
    result = timeString.match(pattern);
    
    var hour   = result[1];
    var minute = result[2];
    var second = result[3];
      
    date.setHours(hour, minute, second);
  }
  
  return date;
}

function sql2ms(dateStr) {
  var date1 = sql2date(dateStr);
  return date1.getTime();
}

function hours_between(datein, dateout) {
  var one_hour = 1000 * 60 * 60;
  return time_between(datein, dateout, one_hour);
}

function days_between(datein, dateout) {
  var one_day = 1000 * 60 * 60 * 24;
  return time_between(datein, dateout, one_day);
}

// todo: consider # days in month
function months_between(datein, dateout) {
  var one_month = 1000 * 60 * 60 * 24 * 30.41666;
  return time_between(datein, dateout, one_month);
}


// returns number of units between 2 days (sql format) (e.g. days/hours/months)
function time_between(datein, dateout, unit_in_ms) {
  if(!unit_in_ms) unit_in_ms = 1000; // default is 1 second
  return (sql2ms(dateout) - sql2ms(datein)) / unit_in_ms;  
  
  // return round_result ? Math.round(difference_ms/unit) : difference_ms/unit;
}

// jquery plugins

// newWindow. From: http://stackoverflow.com/questions/233467/whats-the-best-way-to-open-new-browser-window

(function($){  
  $.fn.newWindow = function(options) {       
    var defaults = {
        titleText: 'Link opens in a new window'         
    };

    var options = $.extend(defaults, options);

     return this.each(function() {  
       var obj = $(this);

       if (options.titleText) {            
           if (obj.attr('title')) {
                     var newTitle = obj.attr('title') + ' (' 
                                                + options.titleText + ')';
           } else {
                    var newTitle = options.titleText;
           };                      
           obj.attr('title', newTitle);                    
       };          

       obj.click(function(event) {
          event.preventDefault();  
          var newBlankWindow = window.open(obj.attr('href'), '_blank');
          newBlankWindow.focus();
        });     
       });    
  };  
 })(jQuery);

 
/*
 * jQuery Hotkeys Plugin
 * Copyright 2010, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 *
 * Based upon the plugin by Tzury Bar Yochay:
 * http://github.com/tzuryby/hotkeys
 *
 * Original idea by:
 * Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
*/

(function(jQuery){
	
	jQuery.hotkeys = {
		version: "0.8",

		specialKeys: {
			8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
			20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
			37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 
			96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
			104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/", 
			112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", 
			120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta"
		},
	
		shiftNums: {
			"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", 
			"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<", 
			".": ">",  "/": "?",  "\\": "|"
		}
	};

	function keyHandler( handleObj ) {
		// Only care when a possible input has been specified
		if ( typeof handleObj.data !== "string" ) {
			return;
		}
		
		var origHandler = handleObj.handler,
			keys = handleObj.data.toLowerCase().split(" ");
	
		handleObj.handler = function( event ) {
			// Don't fire in text-accepting inputs that we didn't directly bind to
			if ( this !== event.target && (/textarea|select/i.test( event.target.nodeName ) ||
				 event.target.type === "text") ) {
				return;
			}
			
			// Keypress represents characters, not special keys
			var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ],
				character = String.fromCharCode( event.which ).toLowerCase(),
				key, modif = "", possible = {};

			// check combinations (alt|ctrl|shift+anything)
			if ( event.altKey && special !== "alt" ) {
				modif += "alt+";
			}

			if ( event.ctrlKey && special !== "ctrl" ) {
				modif += "ctrl+";
			}
			
			// TODO: Need to make sure this works consistently across platforms
			if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
				modif += "meta+";
			}

			if ( event.shiftKey && special !== "shift" ) {
				modif += "shift+";
			}

			if ( special ) {
				possible[ modif + special ] = true;

			} else {
				possible[ modif + character ] = true;
				possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;

				// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
				if ( modif === "shift+" ) {
					possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
				}
			}

			for ( var i = 0, l = keys.length; i < l; i++ ) {
				if ( possible[ keys[i] ] ) {
					return origHandler.apply( this, arguments );
				}
			}
		};
	}

	jQuery.each([ "keydown", "keyup", "keypress" ], function() {
		jQuery.event.special[ this ] = { add: keyHandler };
	});

})( jQuery );

/*
// Collidable Draggables 0.0.1
// http://plugins.jquery.com/files/jquery-collide.js.txt
$.ui.plugin.add("draggable", "collide", {
    start: function(event, ui) {
        var $t = $(this), widget = $t.data("draggable");
        // TODO - make peers configurable
        widget.peers = $t.siblings();
        widget.mode = widget.options.collide;
        // If we're being dragged, then *we're* the overlapper. :)
        if (widget.mode == 'flag') $t.removeClass('ui-draggable-overlapped');
    },

    drag: function(event, ui) {
        var $t = $(this), widget = $t.data("draggable");
        if (widget.mode == 'flag') $t.removeClass('ui-draggable-overlapping');
        $(widget.peers).each(function (i, peer) {
            var $p = $(peer);
            var ix1 = ui.position.left, ix2 = ix1 + $t.width();
            var iy1 = ui.position.top, iy2 = iy1 + $t.height();
            var px1 = $p.position().left, px2 = px1 + $p.width();
            var py1 = $p.position().top, py2 = py1 + $p.height();
            
            // Test for overlap
            if (((ix1 <= px1 && ix2 >= px1) || (ix1 <= px2 && ix2 >= px2)) &&
                ((iy1 <= py1 && iy2 >= py1) || (iy1 <= py2 && iy2 >= py2))) {
                if (widget.mode == 'flag') {
                    $p.addClass('ui-draggable-overlapped');
                    $t.addClass('ui-draggable-overlapping');
                    $p.removeClass('ui-draggable-overlapping');
                } else if (widget.mode == 'block') {
                    // Calculate a ratio of the overlap to decide which face to slide along
                    overlapx = Math.min(ix2, px2) - Math.max(ix1, px1);
                    overlapy = Math.min(iy2, py2) - Math.max(iy1, py1);
                    if (Math.abs(overlapx) > Math.abs(overlapy)) {
                        if (iy1 <= py1) ui.position.top = py1 - $t.height();
                        if (iy1 > py1) ui.position.top = py2;
                    } else {
                        if (ix1 <= px1) ui.position.left = px1 - $t.width();
                        if (ix1 > px1) ui.position.left = px2;
                    }
                }
            } else {
                if (widget.mode == 'flag') {
                    $p.removeClass('ui-draggable-overlapping');
                    $p.removeClass('ui-draggable-overlapped');
                }
            }
        });
    }
});
*/

// end jquery plugins

// jquery date(time)-picker helpers

// thank you rick stahl: http://www.west-wind.com/weblog/posts/891992.aspx
$.maxZIndex = $.fn.maxZIndex = function(opt) {
    /// <summary>
    /// Returns the max zOrder in the document (no parameter)
    /// Sets max zOrder by passing a non-zero number
    /// which gets added to the highest zOrder.
    /// </summary>    
    /// <param name="opt" type="object">
    /// inc: increment value, 
    /// group: selector for zIndex elements to find max for
    /// </param>
    /// <returns type="jQuery" />
    var def = { inc: 10, group: "*" };
    $.extend(def, opt);
    var zmax = 0;
    $(def.group).each(function() {
        var cur = parseInt($(this).css('z-index'));
        zmax = cur > zmax ? cur : zmax;
    });
    if (!this.jquery)
        return zmax;

    return this.each(function() {
        zmax += def.inc;
        $(this).css("z-index", zmax);
    });
}

function update_timefield(fld_name) {
  var $date = $('#' + fld_name);
  var date = strip_time($date.val()); 
  var time = $('#'+ fld_name + '_time').val(); 
  //alert("updating to:" + date + " + " + time);  
  if(date && time) { 
    var datetime = date+ " " + time + ":00";
    $date.val(datetime);
  }
}

function update_dependent_datefield(source, target, num_days) {
  var $source = $('#' + source + '_disp');
  var $target = $('#' + target + '_disp');

  var source_date = $source.datepicker("getDate");
  if(!source_date) return;
  var target_date = add_days(source_date, num_days);
  //alert("source=" + source_date + " add=" + num_days + " target=" + target_date);
  
  $target.datepicker("option", "minDate", source_date);
  var dep_date = $target.datepicker("getDate");
  if(dep_date && source_date.getTime() >= dep_date.getTime()) $target.datepicker("setDate", target_date);
}

// yyyy-mm-dd hh:mm:ss => yyyy-mm-dd
function strip_time(datetime) {
  return datetime.substring(0, 10);
}

// yyyy-mm-dd hh:mm:ss => hh:mm:ss
function strip_date(datetime) {
  return datetime.substring(11);
}

// yyyy-mm-dd hh:mm:ss => hh:mm
function strip_date_sec(datetime) {
  var time = strip_date(datetime);
  return time.substring(0, 5);
}

// checks if javscript Date object date1 is after date2
function is_after(date1, date2) {
  return time_between(date2sql(date1), date2sql(date2)) < 0;
} 
// end datetime.js


// start mapiconmaker.js
/**
 * MapIconMaker v1.0
 * Copyright (c) 2008 Pamela Fox
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 *
 *
 *  Author: Pamela Fox
 *
 *  This gives you static function(s) for creating dynamically sized and
 *  colored marker icons using the Charts API marker output.
 */

var MapIconMaker = {};

MapIconMaker.createMarkerIcon = function(opts) {
  var width = opts.width || 32;
  var height = opts.height || 32;
  var primaryColor = opts.primaryColor || "#ff0000";
  var strokeColor = opts.strokeColor || "#000000";
  var cornerColor = opts.cornerColor || "#ffffff";
   
  var baseUrl = "http://chart.apis.google.com/chart?cht=mm";
  var iconUrl = baseUrl + "&chs=" + width + "x" + height + 
      "&chco=" + cornerColor.replace("#", "") + "," + primaryColor.replace("#", "") + "," + strokeColor.replace("#", "") + "&ext=.png";
  var icon = new GIcon(G_DEFAULT_ICON);
  icon.image = iconUrl;
  icon.iconSize = new GSize(width, height);
  icon.shadowSize = new GSize(Math.floor(width*1.6), height);
  icon.iconAnchor = new GPoint(width/2, height);
  icon.infoWindowAnchor = new GPoint(width/2, Math.floor(height/12));
  icon.printImage = iconUrl + "&chof=gif";
  icon.mozPrintImage = iconUrl + "&chf=bg,s,ECECD8" + "&chof=gif";
  var iconUrl = baseUrl + "&chs=" + width + "x" + height + 
      "&chco=" + cornerColor.replace("#", "") + "," + primaryColor.replace("#", "") + "," + strokeColor.replace("#", "");
  icon.transparent = iconUrl + "&chf=a,s,ffffff11&ext=.png";

  icon.imageMap = [
      width/2, height,
      (7/16)*width, (5/8)*height,
      (5/16)*width, (7/16)*height,
      (7/32)*width, (5/16)*height,
      (5/16)*width, (1/8)*height,
      (1/2)*width, 0,
      (11/16)*width, (1/8)*height,
      (25/32)*width, (5/16)*height,
      (11/16)*width, (7/16)*height,
      (9/16)*width, (5/8)*height
  ];
  for (var i = 0; i < icon.imageMap.length; i++) {
    icon.imageMap[i] = parseInt(icon.imageMap[i]);
  }

  return icon;
}

// end mapiconmaker.js

// start jquery/init.js
// MSIE and Opera doesn't support CSS3 rounded corners, use jquery library curvy corners v 2.0.4
// (auto-disabled for browsers with CSS3 border-radius support.)

if(1) {
$(document).ready(function() {
  $('input').bind('change', function() { formChangedFlag = 'X'; });   
  $('a[rel=external]').click(function() {
    window.open($(this).attr('href'), 'Edit Dialog', "height=900,width=550,modal=yes,alwaysRaised=yes,toolbar=0,location=0,menubar=0");
  });

  // $('a[rel=external]').newWindow( { titleText: 'This is a new window link!' } );

  // if($.browser.msie || $.browser.opera) {
  //   var cc_top = {
  //     tl: { radius: 20 },
  //     tr: { radius: 20 },
  //     antiAlias: true
  //   }
  //   var cc_bottom = {
  //     bl: { radius: 20 },
  //     br: { radius: 20 },
  //     antiAlias: true
  //   }
  //   //$('.round').corner(); 
  //   //$('.round_top').corner(cc_top); 
  //   //$('.round_bottom').corner(cc_bottom); 
  // }
});
}
// end jquery/init.js

// new ajax functions for front-end

// calculate product tax, subtotal, total, show in dialog
function product_update() {
  var amount = parseFloat($("#amount").val());
  var quantity = parseFloat($("#quantity").val());
  var discount = $("#discount").val();
  var tax_included = parseInt($("#tax_included").val());
  var tax_rate = parseFloat($("#tax_percentage").val());
  if(discount) amount = apply_discount(amount, discount);
  
  var subtotal = parseFloat(amount * quantity).toFixed(2); // todo: apply discount

  if(tax_included) {
    var amount_ex_tax = (subtotal / ((tax_rate / 100) + 1)).toFixed(2);       
    var tax_of_which = (subtotal - amount_ex_tax).toFixed(2);
    var tax = 0;
  } else {
    var tax = (subtotal * (tax_rate / 100)).toFixed(2);
    var tax_of_which = 0;
  }
          
  var total = (parseFloat(subtotal) + parseFloat(tax)).toFixed(2);
//  var total = (subtotal + tax).toFixed(2);

  if(tax_rate > 0) { 
    $("#tax_included_text").html(tax_included ? "Including tax" : "Excluding tax");
  } else {
    $("#tax_included_text").html('');
  }
  
  $("#total").val(total);
  $("#subtotal").val(subtotal);

  // $("#discount").val(0);
  $("#tax_text").html(tax_rate > 0 ? "Of which tax: " +  (tax_included ? tax_of_which : tax) : '');
  //alert(responseText);
}

// returns array(abs_discount, perc_discount)
function split_discount(discount) {
  pos = discount.indexOf('%');
  if(pos > 0) { // % discount
    return [0, parseFloat(discount.substr(0, pos))];
  } else { // absolute discount
    return [parseFloat(discount), 0];
  }
}

function apply_discount(price, discount) {
  if(!discount) return price;
  var disAr = split_discount(discount);
  var abs_discount = disAr[0];
  var perc_discount = disAr[1];
  if(perc_discount > 0) {
    return (price * (100 - perc_discount) / 100).toFixed(2); 
  } else if(abs_discount > 0) {
    return (price - abs_discount).toFixed(2);
  }
}

// fetch product from database, populate dialog
function product_fetch() {
  // alert('product update');
  var product_id = $("#product_id").val();
  if(product_id) {
    ajax_url = "/admin/app_data.php?oper=view&obj_type=product&id=" + product_id;
    jQuery.ajax({
      type: "POST",
      url: ajax_url,
      data: "nh=1",
      cache: false,
      async: false,
      success: function(responseText) {
        var response = jQuery.parseJSON(responseText);            
        var product = jQuery.parseJSON(response.data);
        // alert(dump(product));

        $("#currency").val(product.currency);
        $("#amount").val(product.price);
        $("#description").val(product.name);
        $("#tax_percentage").val(product.tax_percentage);
        $("#tax_included").val(product.tax_included);
         
        product_update();

      }
    });
  }
}

function loadProperties(url) {
  $('#searchbox').addClass('disabled');
  //alert(url);
  // if(url.indexOf('560') > 0)
  // $('#searchbox').html("<div class='spinning_wheel'>Loading...</div>");
  jQuery.ajax({
    type: "POST",
    url: url,
    data: "ajax_load=1",
    cache: false,
    async: false,
    success: function(responseText) {
      $('#searchbox').removeClass('disabled');
    	var result = jQuery.parseJSON(responseText);
      $('#searchbox').html(result.search);
      $('#searchresult').html(result.data);
      eval(result.map);
      var $map = $("#search_result_map"); 
      $map.gmap("clear", "markers");
      gmap3_loadmarkers('search_result_map', markers);
      // var map_options = $map.data('options');

      var $popup_map = $("#gmap_popup"); 
      var map_options = result.map_options;
      // alert(dump(map_options));

      gmap3_maplink_init(map_options);
      $map.gmap("refresh");
    },
    error: function(request, error) {
      alert("Error: " + error)     
      $('#searchbox').removeClass('disabled');
    }
  });
}

function reset_product_form() {
  $("#product_id").val("");
  $("#product_id_textbox").val("");
  $("#quantity").val("1");
  $("#amount").val("");
  $("#description").val("");
  $("#total").val("");
  $("#tax_percentage").val("");
  $("#tax_included").val("");
  $("#tax_included_text").val("");
}

function add_product_handler() {
  reset_product_form();
}

function gallery_upload_handler(data) {
  // alert(dump(data));
  var $gallery = $('#gallery');
  var id = data.id;
  var path = data.path;
  var filename = data.src;
  var info_fields = data.info_fields;
  
  // alert('file=' + data.qqfile + " fn=" + data.filename);
  
  var desc = 'Coming soon...';
  var thumb_dir = gallery_resize.thumb ? gallery_resize.thumb[1] + '/' : '';
  var big_dir = gallery_resize.big ? gallery_resize.big[1]  + '/' : '';
  var full_dir = gallery_resize.full ? gallery_resize.full[1]  + '/' : '';

  var thumb = path + thumb_dir + filename;
  var big = path + big_dir + filename;
  var full = path + full_dir + filename;
    
  var img = ' 	<li id="li_' + id + '" class="ui-widget-content ui-corner-tr float_left">\n' +
            '    <h5 id="lih_' + id + '" class="ui-widget-header">' + filename + '</h5>\n' +
            '    <img id="img_' + id + '" src="' + thumb + '" alt="' + filename+ '" width="96" height="72"/>\n' +
            '    <a id="mag_' + id + '" href="' + big + '" target="pic" title="' + desc + '" class="preview ui-icon ui-icon-zoomin">View larger</a>\n' +
            '    <a href="link/to/trash/script/when/we/have/js/off" title="Delete this image" class="ui-icon ui-icon-trash">Delete image</a>\n' +
            '  </li>';   
    
  $gallery.append(img);
  gallery_update_handler(data);
  imagePreview();
  edit_gallery_init(0);
}                    

function gallery_update_handler(data) {
  var $img = $('#img_' + data.id);
  var $mag = $('#mag_' + data.id);
  $img.data('info', data);
  var vals = [$img.attr('alt')];
  $.each(gallery_info_fields, function(key, name) {
    var val = eval('data.' + key);
    vals.push(val);
  });
  var new_title = vals.join("<br>");     
  $mag.attr('title', new_title);
}
    
function edit_gallery_init(id) {
  // there's the gallery and the trash
  var $gallery = $('#gallery'), $trash = $('#trash');

  // let the gallery be sortable
  $gallery.sortable({
    containment: $('#gallery_frame').length ? '#gallery_frame' : 'document', // stick to gallery_frame if present
    cursor: 'move',
    update: function(event, ui) {
      var imgArray = $(this).sortable("toArray");
      var ids = new Array();
      var ranks = new Array();
      $.each(imgArray, function(index, value) {
        id = value.replace("li_", "");
        rank = parseInt(index) + 1;
        ids.push(id);
        ranks.push(rank);
      });
      var first_src = $("#"+ids[0]+"").attr("src");
      $("#title_photo_' + id + '").attr("src", first_src);
      var ids_str = ids.toString();
      var ranks_str = ranks.toString();
      $.ajax({ url: "/admin/app_data.php?obj_type=media", type: "POST", data: "obj_type=media&oper=edit&data_field=rank&id="+ ids_str + "&rank="+ranks_str });
    }
    //cancel: 'a.ui-icon',// clicking an icon won't initiate dragging
    //revert: 'invalid', // when not dropped, the item will revert back to its initial position
    //helper: 'clone',

  });

  // let the trash be droppable, accepting the gallery items
  $trash.droppable({
    accept: '#gallery > li',
    activeClass: 'ui-state-highlight',
    drop: function(ev, ui) {
      deleteImage(ui.draggable);
    }
  });

  // let the gallery be droppable as well, accepting items from the trash
  $gallery.droppable({
    accept: '#trash li',
    activeClass: 'custom-state-active',
    drop: function(ev, ui) {
      recycleImage(ui.draggable);
    }
  });

  function emptyTrashButton(correction) {
    var $was= $('li',$trash).length;
    var $now = $was + correction;
    if($now > 0) $("#gallery_empty_trash").show();
    else $("#gallery_empty_trash").hide();
  }

  // image deletion function
  var recycle_icon = '<a href="link/to/recycle/script/when/we/have/js/off" title="Recycle this image" class="ui-icon ui-icon-refresh">Recycle image</a>';
  function deleteImage($item) {
    $item.fadeOut(function() {
      var $list = $('ul',$trash).length ? $('ul',$trash) : $('<ul class="gallery ui-helper-reset"/>').appendTo($trash);
      //alert("got here2 trash length = " + $('ul',$trash).length);
      $item.find('a.ui-icon-trash').remove();
      $item.append(recycle_icon)
        .appendTo($list)
        .fadeIn(function() {
          $item.animate({ width: '48px' })
          .find('img')
          .animate({ height: '36px' });
        });
    });
    // use ajax to set image inactive
    var img_id = $item.find('img').attr("id");				
    img_id = img_id.substr(4); // strip leaing img_
    var $url = "/admin/app_data.php?obj_type=media";
    //alert($url + "id=" + img_id);
    $.ajax({ url: $url, type: "POST", data: "obj_type=media&oper=edit&active=0&id="+img_id});
    emptyTrashButton(1);
  }

  // image recycle function
  var trash_icon = '<a href="link/to/trash/script/when/we/have/js/off" title="Delete this image" class="ui-icon ui-icon-trash">Delete image</a>';
  function recycleImage($item) {
    $item.fadeOut(function() {
      $item.find('a.ui-icon-refresh').remove();
      $item.css('width','96px').append(trash_icon).find('img').css('height','72px').end().appendTo($gallery).fadeIn();
    });
    // use ajax to set image active
    var img_id = $item.find('img').attr("id");
    img_id = img_id.substr(4); // strip leaing img_
    $.ajax({ url: "/admin/app_data.php?obj_type=media", type: "POST", data: "obj_type=media&oper=edit&active=1&id="+img_id});
    emptyTrashButton(-1);
  }

  // image preview function, demonstrating the ui.dialog used as a modal window
  function viewInfoDialog($item, $link) {
    var id = get_target_id($item);
    if(id) {
      var prefix = "";
      var $img = $("#img_" + id);
      $("#image_info_preview").attr("src", $img.attr("src"));
      var data = $img.data("info");
      $("#" + prefix + "id").val(id);
      $.each(data, function(k, v) {
        $("#" + prefix + k).val(v);
        //alert(k + "=" + v); 
      });
    }
    var title = $img.attr("alt");
    var dialog = $("#image_info_dialog");
    setTimeout(function() {
      dialog.dialog({
          title: title,
          width: 400,
          modal: true
        });
    }, 1);

  }

  $('#gallery_empty_trash').click(function(ev) {
    if(!confirm('Are you sure you want to permanently delete the images in the trash?')) return false;
    var imgArray = $('#trash ul img'); //.sortable("toArray");
    var ids = new Array();
    $.each(imgArray, function(index, value) {
      img_id = value.id;
      img_id = img_id.substr(4); // strip leaing img_
      ids.push(img_id);
    });
    var ids_str = ids.toString();
    $.ajax({ url: "/admin/app_data.php?obj_type=media", type: "POST", data: "obj_type=media&oper=del&id="+ ids_str });
    $('#trash ul li').remove();
    emptyTrashButton(-1);
    return false;
  });                 

  // resolve the icons behavior with event delegation
  $('ul.gallery > li').click(function(ev) {
    var $item = $(this);
    var $target = $(ev.target);

    if ($target.is('a.ui-icon-trash')) {
      deleteImage($item);
    } else if ($target.is('a.ui-icon-zoomin')) {
      viewInfoDialog($item, $target);
    } else if ($target.is('a.ui-icon-refresh')) {
      recycleImage($item);
    }

    return false;
  });
  
  $('ul.gallery > li').dblclick(function(ev) {         
//  $('ul.gallery > li').on("dblclick", function(ev) {         
    var $item = $(this);
    var $target = $(ev.target);
    viewInfoDialog($item, $target);
    return false;
  });
  
}

function reload_page() {
  window.location.reload();
}

// new ajax functions for back-end
function delete_object(obj_type, id, success_handler, reload, keepalive) {
  var ajax_url = '/admin/app_data.php?obj_type='+ obj_type + '&id=' + id + '&oper=del';
  jQuery.ajax({
    type: "POST",
    url: ajax_url,
    success: function (responseText) {
      //alert(dump(responseText));
      var result = jQuery.parseJSON(responseText);
      var success = result.success;
      var message = result.message;
      var data = result.data;
      var error = result.error;
      // var $messages = $('#' + form_id + '_messages');
      // var $errors = $('#' + form_id + '_errors');
      // if(error) $errors.html(error);
      // if(message) $messages.html(message);
      // alert("keepalive=" + keepalive + dump(result));
      if(error) alert(error);
      if(result.success == 1) {        
        //alert('success:' + message);
        if(success_handler) {
          var funcCall = success_handler  + "(" + data + ");";
          eval(funcCall);
        }
        if(keepalive == 1) {
        } else {
          //close_parent_dialog(form_id);
          if(reload) reload_page();
        }
      } else {
        // $messages.html(message);
        //alert('failure:' + message + " selector=" + selector +  " len=" + $(selector).length);
      }
    },
    error: function(request, error) {
      alert("Error: " + error)     
    }
  });
  return false;
}

function save_object(form_id, obj_type, action, success_handler, reload, keepalive) {
  var ajax_url = '/admin/app_data.php?obj_type='+ obj_type + '&oper=' + action;
  jQuery.ajax({
    type: "POST",
    data: $("#" + form_id).serialize(),
    url: ajax_url,
    success: function (responseText) {
      //alert(dump(responseText));
      var messages = [];
      var result = jQuery.parseJSON(responseText);
      var success = result.success;
      var message = result.message;
      var data = result.data;
      var error = result.error;
      var $messages = $('#' + form_id + '_messages');
      var $errors = $('#' + form_id + '_errors');
      if(message) messages.push(message);
      // alert("keepalive=" + keepalive + dump(result));
      if(result.success == 1) {        
        //alert('success:' + message);
        if(success_handler) {
          var funcCall = success_handler  + "(" + data + ");";
          eval(funcCall);
        }
        if(keepalive == 1) {
          //messages.push("Added product " + data.name);
        } else {
          close_parent_dialog(form_id);
          if(reload) reload_page();
        }
      } else {
        //$messages.html(message);
        //alert('failure:' + message + " selector=" + selector +  " len=" + $(selector).length);
      }
      if(error) $errors.html(error);
      if(messages.length) $messages.append(messages.join('<br>'));
      
    },
    error: function(request, error) {
      alert("Error: " + error)     
    }
  });
  return false;
}

// if element is contained in a dialog, close this
function close_parent_dialog(id) {
  $el = $('#' + id);
  if(!$el.length) return false;  
  $dialog = $el.closest('.ui-dialog-content');
  if(!$dialog.length) return false;
  $dialog.dialog('close');
  return true;
}

function save_object_dialog(parent_id, obj_type, form_id, unauthenticated) {
  var $dialog = $('#new_object_dialog');
  var $dialog_errors = $('#new_object_dialog_errors');
  var $dialog_messages = $('#new_object_dialog_messages');
  var form_data_str = $('#' + form_id).serialize();
  //ajax_url = "/admin/app_data.php?oper=add&" + form_data_str;
  // var form_data = $('#' + form_id);

  ajax_url = "/" + (unauthenticated ? "home" : "admin") + "/app_data.php?oper=add&obj_type=" + obj_type;
  //alert(ajax_url);

  jQuery.ajax({
    type: "post",                                                         
    data: $('#' + form_id).serialize(),
    url: ajax_url,
    success: function (responseText) {
      $dialog_messages.html(responseText);
      if(responseText.indexOf('OK:') == 0) {
        //alert('YES! ' + responseText);
        var pos;
        //if(pos = responseText.indexOf("\n")) responseText 
        // remove custom lines if any
        
        temp = responseText.split(' ');
        var result    = temp.shift();
        var oper      = temp.shift();
        var obj_type  = temp.shift();
        var obj_id    = temp.shift();
        var descriptor = temp.join(' ');
        descriptor = descriptor.slice(1, descriptor.length-1); // remove opening and closing parenthesis
        var $parent = $('#' + parent_id);
        var $parent_text = $('#' + parent_id + '_textbox');
        if ($parent.is('select')) { // select box
          $parent.
            append($("<option></option>").
            attr("value",obj_id).
            text(descriptor));
          $parent.val(obj_id);
        } else if ($parent_text.length && $parent_text) { // ajax chooser: todo, check for in
          //alert('new ajax_chooser');
          $parent.val(obj_id);
          $parent_text.val(descriptor);
        } else if ($parent.length) { // some - div info text field
          // alert('writing' + responseText + ' to ' + parent_id);
          $parent.html(responseText);
        } else {
          alert('??');
          $parent.val(obj_id);
        }
        // alert(' Result:' + result + ' oper:' + oper + ' ot:' + obj_type + ' id:' + obj_id + ' desc:' + descriptor);
        $dialog.dialog('close');
      } else {
        // alert('nope');
      }
    }
  });
}

// the latest
function object_dialog(obj_type, id, fields, data, handler, reload, unauthenticated) {
  //var dialog_id = obj_type + '_dialog';
  var dialog_id = 'object_dialog';
  var $dialog = $('#' + dialog_id);
                   
  $dialog = $dialog.length && $dialog || $('<div id="' + dialog_id + '"></div>').appendTo('body');  // append if doesn't exist
  $dialog.html('Loading...');
  $dialog.dialog({   
   autoOpen: false,
   closeOnEscape: false,
   modal: true,
   title: "Loading...",
   width: 500
  });

//   width: 1000,
//   height: 1000
  
  $dialog.dialog('open'); // jquery call to show overlay
  load_dialog(obj_type, id, fields, data, handler, reload, unauthenticated);
  
  // ajax_url = "/" + (unauthenticated ? "home" : "admin") + "/app_data.php?oper=load_dialog&obj_type=" + obj_type + "&id=" + id;
  // if(fields) ajax_url = ajax_url + "&fields=" + array2json(fields);
  // //alert(ajax_url);
  // $dialog.load(ajax_url, function (responseText) {
  //   $dialog.dialog('option', 'title', title);
  //   loadEditors('#'+dialog_id + ' textarea.jqckeditor');
  //   //.ckeditor();
  // });                                    
}

function load_dialog(obj_type, id, fields, data, handler, reload, unauthenticated) {  
  var dialog_id = 'object_dialog';
  var $dialog = $('#' + dialog_id);
  var action = id ? 'Edit' : 'Add';
  var title = action + ' ' + obj_type + ' ' + id;
  var reload_bool = typeof reload !== "undefined" && reload ? 1 : 0; 
  // $dialog.data('reloadfoo', (reload ? 1 : 0));
  // $dialog.data('reloadfoo', "hello");
  // alert("load: reload=" + reload + ' bool =' + reload_bool); 

  ajax_url = "/" + (unauthenticated ? "home" : "admin") + "/app_data.php?oper=load_dialog&obj_type=" + obj_type + "&id=" + id + "&reload=" + reload_bool;
  if(fields) ajax_url += "&fields=" + array2json(fields);
  if(handler) ajax_url += '&handler=' + handler;
  // alert(ajax_url);
  // alert(dump(data));
  $dialog.load(ajax_url, data, function (responseText) {
    $dialog.dialog('option', 'title', title);
    loadEditors('#'+dialog_id + ' textarea.jqckeditor');
    //.ckeditor();
  });                                    

  //jQuery.ajax({
  //  type: "POST",
  //  data: data,
  //  url: ajax_url,
  //  success: function (responseText) {
  //    $dialog.html(responseText);
  //  },
  //  error: function(request, error) {
  //    alert("Error: " + error)     
  //  }
  //});

}
  
// loops through all elements in selector and make them ckeditors unless they're already so
function loadEditors(selector) {    
  var $editors = $(selector);
  var count = $editors.length;
  if (count) {
    //options = { toolbar : [ ['Source'], ['Bold','Italic','Underline','Strike'], ], height: 600, width: 900 };
    options = { height: 400, width: 600 };
    $editors.each(function() {
      var editorID = $(this).attr("id");
      var instance = CKEDITOR.instances[editorID];        
      if (instance) {
        CKEDITOR.remove(instance);
        CKEDITOR.replace(editorID, options);
      } else {          
        $(this).ckeditor(options);          
      }
      //alert(editorID + 'is CK? ' + isck);                 
    });
  }
}

function new_object_dialog(parent_id, obj_type, title, unauthenticated) {
  var $dialog = $('#new_object_dialog');
  $dialog = $dialog.length && $dialog || $('<div id="new_object_dialog"></div>').appendTo('body');  // append if doesn't exist
  $dialog.html('Loading...');
  $dialog.dialog({   
   autoOpen: false,
   closeOnEscape: false,
   modal: true,
   title: title,
   width: 450,
   height: 700
  });
  $dialog.dialog('option', 'title', 'Loading...'); 
  $dialog.dialog('open'); // jquery call to show overlay
  ajax_url = "/" + (unauthenticated ? "home" : "admin") + "/app_data.php?oper=new_object_dialog&obj_type=" + obj_type + "&inline_pid=" + parent_id;
  //alert(ajax_url);
  $dialog.load(ajax_url, function (responseText) {
    $dialog.dialog('option', 'title', title);
  });                                    
}

/*
function edit_page_dialog(site_id, id, is_folder, handler) {
  var title = "Edit " + (is_folder ? "folder" : "page") + ' ' + id;
  var $dialog = $('#site_page_dialog');
  $dialog.html("Loading...");
  $dialog.show();
  $dialog.dialog({ draggable: true, height: 600,  width: 800,  position: [0, 0],  title: title});
  //ajax_url = "/admin/app_data.php?oper=load_dialog&obj_type=site_page&id=" + node.data.key + "&site_id=" + site_id;
  ajax_url = "/admin/app_data.php?oper=load_dialog&obj_type=site_page&site_id=" + site_id + "&id=" + id + "&is_folder=" + is_folder + '&handler=' + handler;
  $dialog.load(ajax_url, function (responseText) {
    $('#page_edit_form').show();
  });              
  
}

function add_page_dialog(site_id, parent_id, is_folder, handler) {
  var title = "Add " + (is_folder ? "folder" : "page");
  var $dialog = $('#site_page_dialog');
  $dialog.html("Loading...");
  $dialog.show();
  $dialog.dialog({ draggable: true, height: 800,  width: 300,  position: [0,0],  title: title});
  ajax_url = "/admin/app_data.php?oper=load_dialog&obj_type=site_page&site_id=" + site_id + "&parent_id=" + parent_id + "&is_folder=" + is_folder + '&handler=' + handler;
  $dialog.load(ajax_url, function (responseText) {
    //alert(responseText);
    $('#page_edit_form').show();
  });              

  //var title = active ? "Edit " + active.data.title : ("Add " + is_folder ? "folder" : "page");
  //alert(title + " for site " + site_id + " under page " + parent_id); 
  //  if(active) title += " under "+ active.data.title
  // alert("click on tree " + id + " active =" + (active ? active.data.title : '') + " root=" + rootNode.data.title);
  //return false;

}
*/


function delete_uploaded_file(parent_id, list_index, filename) {
  ajax_url = "/admin/app_data.php?oper=delete_file";
  jQuery.ajax({
    type: "post",
    data: "filename="+filename,
		// contentType: "application/json; charset=utf-8",
		// dataType: "json",
    url: ajax_url,
    success: function (responseText) {
    	var result = jQuery.parseJSON(responseText);
    	if(result.success == '1') {
				// remove item from screen list and hidden field
				$('#' + parent_id +'-filelist li:nth-child(' + list_index + ')').remove();
				//$item.remove();
				var $target = $('#' + parent_id);
				var val = $target.val();
				if(val && list_index) {
					var files = val.split(",");										
					//files = removeArrayElement(files, list_index - 1, 0); // index is 1 based. Arrays zero based
					files.splice(list_index - 1, 1); // List_index is 1 based. Arrays zero based
          // alert(val + '<br>' + files.join(',') + '<br>' + 'list_index = ' + list_index);
					$target.val(files.join(','));							
      	}
      } else {
    		alert('Could not delete file ' + filename);      	
    		// alert('Could not delete file:' + responseText);      	
    	}
    }
  });
}

function save_layout() {
  var $errors = $('#layout_errors');
  var $messages = $('#layout_messages');
  $("#div_select").attr("disabled", false);
  // var form_data_str = $('#layout_form').serialize();
  ajax_url = "/admin/app_data.php?oper=save_layout";
  var $selected = $("#div_select option:selected"); 
  var val  = $selected.val();
  if(!val) {alert("Save Layout: No element selected");return false;}
  var selector = $selected.text();
  var remote = $(window.opener).length == 1;
  var $target = remote ? window.opener.$(selector) : $(selector);
                       
  // alert(ajax_url);  
  $("#css_save").attr('disabled', true);
  $("#css_cancel").attr('disabled', true);  
  $("#css_saving").show();

  jQuery.ajax({
    type: "post",
    data: $('#layout_form').serialize(),
    url: ajax_url,
    success: function (responseText) {
      if(responseText.indexOf('OK:') == 0) {
        $messages.html(responseText);
        $("#css_saving").hide();
        //layout_save_original($target, g_css_selectors);
        $("#page_id").attr('disabled', false);
        layout_select_div(selector); // this calls layout_save_original()
        //var loc = document.location.toString();
        //var location_arr = loc.split('?');
        // window.opener.document.location = location_arr[0] + '?css_edit=' + escape(selector); // reload
      } else {
        $errors.html(responseText);
        $("#css_saving").hide();
        $("#css_save").attr('disabled', false);
        $("#css_cancel").attr('disabled', false);  
      }
    }
  });
}			

// opens a modal dialog for previewing a uri
function preview_dialog(title, ajax_url) {
  var $dialog = $('#preview_dialog');
  $dialog = $dialog.length && $dialog || $('<div id="preview_dialog"><iframe id="preview_iframe" width="100%" height="100%">No iFrame support</iframe></div>').appendTo('body');  // append if doesn't exist
  //$dialog.html('Loading...');
  $dialog.dialog({   
   autoOpen: false,
   closeOnEscape: false,
   modal: true,
   title: title,
   width: 1024,
   height: 768
  });                                                 
  $dialog.dialog('open'); // jquery call to show overlay
  $('#preview_iframe').attr('src', ajax_url); 
}

// end new ajax function for back-end


// begin ajaxsuggest.js
var selected_index = 0;
var user_input = '';
var min = 3;
var max = 10;
var num_suggestions = 0;


function ajaxChooser(evt, str, fld, obj_type, filters, handler, onchange)
{

  if(window.event) { // Internet Exploder
    key = event.keyCode;
  } else { // compliant browser
    key = evt.keyCode;
  }
  var suggestion_id   = fld + '_suggestions';
  var spinning_image = "url(/images/icons/spinning_wheel.gif)";
  var search_image = "url(/images/icons/suggest_bg.gif)";

  var $suggestion_div  = $('#' + suggestion_id);
  var input_div       = document.getElementById(fld + '_textbox');
  //var index_div       = document.getElementById(fld + '_index');
  var value_div       = document.getElementById(fld);

  //vis = suggestion_div.style.display=='block' ? true : false;

  var vis = $suggestion_div.is(':visible');
  //alert('table=' + table + ' sf=' + search_field + ' vf=' + value_field);
  // count # suggestions
  // reset all to unselected
  // num_suggestions = 1;
  //   tid='s_line_' + num_suggestions;
  // while(document.getElementById(tid)) {
  //   num_suggestions++;
  //   tid='s_line_' + num_suggestions;
  // }
  // document.getElementById(index_div).value = num_suggestions - 1;
  // //alert('# suggestions=' + num_suggestions);

  // key handler
  if(key != 8 && key < 60 && !vis) return; // don't process if suggestion is hidden and non-ascii key
  if(key==40) { // down
    if(++selected_index > max) selected_index=max;
    //if(selected_index > 1) alert("max=" + max + "si=" + selected_index + " vis=" + vis);
    return vis ? hilite2(fld, selected_index): "";
  } else if(key==38) { // up
    if(--selected_index<=0) { // user went up above first suggestions
      input_div.value = user_input; // restore what user typed
      value_div.value = '';
      return hideSuggestions(fld);
    } else {
      return vis ? hilite2(fld, selected_index): "";
    }
  } else if(key==27) { // escape
    return hideSuggestions(fld);
  } else if(key==8) { // backspace
    user_input = input_div.value; // store what user types
    $suggestion_div.html('');
    //index_div.value = user_input;
    value_div.value = '';
    // do nothing
  } else if(key==20) { // caps lock
    //alert('caps lock');
  } else if(key==9) { // tab
    //alert('tab');
    return hideSuggestions(fld);
  } else if(key==13) { // return
    return hideSuggestions(fld);
  } else if(key == 32 || key>60) { // space or ascii
    user_input = input_div.value; // store what user types
    //index_div.value = user_input;
    value_div.value = '';
    if(user_input.length >= min) showEl(suggestion_id);
    //return;
  } else {
    //alert('key not handled=' + key);
    $suggestion_div.hide();
    //return hideSuggestions(fld);
  }

  if(user_input.length < min) {
    $suggestion_div.hide();
    return; 
    //hideSuggestions(fld);
  }

  var xmlHttp;
  try {  // Firefox, Opera 8.0+, Safari
    xmlHttp=new XMLHttpRequest();
  }
  catch (e) {  // Internet Explorer
    try {
      xmlHttp=new ActiveXObject("Msxml2.XMLHTTP");
    }
    catch (e) {
      try {
        xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
      }
        catch (e) {
        alert("Your browser does not support AJAX!");
        return false;
      }
    }
  }

  // Ajax is supported
  xmlHttp.onreadystatechange=function()
  {
  if(xmlHttp.readyState==4) { // ready
      var t = xmlHttp.responseText; 
            
      input_div.style.backgroundImage = search_image; // stop spinning   
      input_div.style.backgroundColor = '#fff';

      if(document.getElementById(fld+ '_s_line_1') && !document.getElementById(fld + '_s_line_2')) { // exactly 1 suggestion
        hideEl(suggestion_id);
        var hit_div = document.getElementById(fld + '_s_line_1');
        var hit = hit_div.innerHTML;
        var hit_value = hit_div.title ? hit_div.title : hit_div.name;

        //alert('one hit=' + hit);
        input_div.value = hit;
        value_div.value = hit_value;

      } else if(t.length && user_input.length >= min) { // more than 1 suggesion
        showEl(suggestion_id);
        input_div.style.backgroundColor = '#fff';

        // mark search text in bold
        // t = t.replace(str, '<b>' + str + '</b>');

        $suggestion_div.html(t);


      } else {
        //alert('no matches');
        input_div.style.backgroundColor = '#faa'; // no hits
        hideEl(suggestion_id);
      }

    } else if(xmlHttp.readyState==1) { // not ready (has been set up)

      //hideSuggestions(fld);
      input_div.style.backgroundColor = '#fff';
      hideEl(suggestion_id);
    }
  }

  input_div.style.backgroundImage = spinning_image; // stop spinning   
    
  var theurl="/home/ajax/" + handler + ".php" + "?q="+str+"&target="+fld+"&obj_type="+obj_type;
  if(filters) theurl = theurl + "&filters="+filters;
  //alert(theurl);
  xmlHttp.open("GET",theurl,true);
  xmlHttp.send(null);
}


function hilite2(fld, sel_index) {  

  // reset all to unselected
  for(i=1;i<11;i++) {
    var tid = fld + '_s_line_'+i;
    var el =  document.getElementById(tid);
    if(el) {
      el.style.background= "#fff";
      el.style.color = "#000";
    }
  }

  // hilite selected index
  var elid = fld + '_s_line_' + sel_index;
  var el =  document.getElementById(elid);
  if(el) {
    
    var geourl = el.title ? el.title : el.name; // title sup. by mozilla, name by IE
    var input_div = fld + '_textbox';

    // writes to the 3 boxes; text input, id, index
    document.getElementById(input_div).value = el.innerHTML;
    document.getElementById(fld).value = geourl;

    selected_index = sel_index;
    el.style.background= "#00a";
    el.style.color = "#fff";
  }
}

function hideSuggestions(fld) {
  //alert('hideSug');
  var val = $('#' + fld).val();
  var suggestion_id   = fld + '_suggestions';
  //if(val != '')  
  //alert(val);
  $('#' + suggestion_id).val('').hide();
  // selected_index = 0;
  // document.getElementById(fld).innerHTML = '';
  // hideEl(fld);
}

// end ajaxsuggest.js

// begin jquery/tooltip.js
/*
 * jQuery Tooltip plugin 1.3
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
 * http://docs.jquery.com/Plugins/Tooltip
 *
 * Copyright (c) 2006 - 2008 J�rn Zaefferer
 *
 * $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
 * 
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
 
;(function($) {
	
		// the tooltip element
	var helper = {},
		// the current tooltipped element
		current,
		// the title of the current element, used for restoring
		title,
		// timeout id for delayed tooltips
		tID,
		// IE 5.5 or 6
		IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent),
		// flag for mouse tracking
		track = false;
	
	$.tooltip = {
		blocked: false,
		defaults: {
			delay: 200,
			fade: false,
			showURL: true,
			extraClass: "",
			top: 15,
			left: 15,
			id: "tooltip"
		},
		block: function() {
			$.tooltip.blocked = !$.tooltip.blocked;
		}
	};
	
	$.fn.extend({
		tooltip: function(settings) {
			settings = $.extend({}, $.tooltip.defaults, settings);
			createHelper(settings);
			return this.each(function() {
					$.data(this, "tooltip", settings);
					this.tOpacity = helper.parent.css("opacity");
					// copy tooltip into its own expando and remove the title
					this.tooltipText = this.title;
					$(this).removeAttr("title");
					// also remove alt attribute to prevent default tooltip in IE
					this.alt = "";
				})
				.mouseover(save)
				.mouseout(hide)
				.click(hide);
		},
		fixPNG: IE ? function() {
			return this.each(function () {
				var image = $(this).css('backgroundImage');
				if (image.match(/^url\(["']?(.*\.png)["']?\)$/i)) {
					image = RegExp.$1;
					$(this).css({
						'backgroundImage': 'none',
						'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
					}).each(function () {
						var position = $(this).css('position');
						if (position != 'absolute' && position != 'relative')
							$(this).css('position', 'relative');
					});
				}
			});
		} : function() { return this; },
		unfixPNG: IE ? function() {
			return this.each(function () {
				$(this).css({'filter': '', backgroundImage: ''});
			});
		} : function() { return this; },
		hideWhenEmpty: function() {
			return this.each(function() {
				$(this)[ $(this).html() ? "show" : "hide" ]();
			});
		},
		url: function() {
			return this.attr('href') || this.attr('src');
		}
	});
	
	function createHelper(settings) {
		// there can be only one tooltip helper
		if( helper.parent )
			return;
		// create the helper, h3 for title, div for url
		helper.parent = $('<div id="' + settings.id + '"><h3></h3><div class="body"></div><div class="url"></div></div>')
			// add to document
			.appendTo(document.body)
			// hide it at first
			.hide();
			
		// apply bgiframe if available
		if ( $.fn.bgiframe )
			helper.parent.bgiframe();
		
		// save references to title and url elements
		helper.title = $('h3', helper.parent);
		helper.body = $('div.body', helper.parent);
		helper.url = $('div.url', helper.parent);
	}
	
	function settings(element) {
		return $.data(element, "tooltip");
	}
	
	// main event handler to start showing tooltips
	function handle(event) {
		// show helper, either with timeout or on instant
		if( settings(this).delay )
			tID = setTimeout(show, settings(this).delay);
		else
			show();
		
		// if selected, update the helper position when the mouse moves
		track = !!settings(this).track;
		$(document.body).bind('mousemove', update);
			
		// update at least once
		update(event);
	}
	
	// save elements title before the tooltip is displayed
	function save() {
		// if this is the current source, or it has no title (occurs with click event), stop
		if ( $.tooltip.blocked || this == current || (!this.tooltipText && !settings(this).bodyHandler) )
			return;

		// save current
		current = this;
		title = this.tooltipText;
		
		if ( settings(this).bodyHandler ) {
			helper.title.hide();
			var bodyContent = settings(this).bodyHandler.call(this);
			if (bodyContent.nodeType || bodyContent.jquery) {
				helper.body.empty().append(bodyContent)
			} else {
				helper.body.html( bodyContent );
			}
			helper.body.show();
		} else if ( settings(this).showBody ) {
			var parts = title.split(settings(this).showBody);
			helper.title.html(parts.shift()).show();
			helper.body.empty();
			for(var i = 0, part; (part = parts[i]); i++) {
				if(i > 0)
					helper.body.append("<br/>");
				helper.body.append(part);
			}
			helper.body.hideWhenEmpty();
		} else {
			helper.title.html(title).show();
			helper.body.hide();
		}
		
		// if element has href or src, add and show it, otherwise hide it
		if( settings(this).showURL && $(this).url() )
			helper.url.html( $(this).url().replace('http://', '') ).show();
		else 
			helper.url.hide();
		
		// add an optional class for this tip
		helper.parent.addClass(settings(this).extraClass);

		// fix PNG background for IE
		if (settings(this).fixPNG )
			helper.parent.fixPNG();
			
		handle.apply(this, arguments);
	}
	
	// delete timeout and show helper
	function show() {
		tID = null;
		if ((!IE || !$.fn.bgiframe) && settings(current).fade) {
			if (helper.parent.is(":animated"))
				helper.parent.stop().show().fadeTo(settings(current).fade, current.tOpacity);
			else
				helper.parent.is(':visible') ? helper.parent.fadeTo(settings(current).fade, current.tOpacity) : helper.parent.fadeIn(settings(current).fade);
		} else {
			helper.parent.show();
		}
		update();
	}
	
	/**
	 * callback for mousemove
	 * updates the helper position
	 * removes itself when no current element
	 */
	function update(event)	{
		if($.tooltip.blocked)
			return;
		
		if (event && event.target.tagName == "OPTION") {
			return;
		}
		
		// stop updating when tracking is disabled and the tooltip is visible
		if ( !track && helper.parent.is(":visible")) {
			$(document.body).unbind('mousemove', update)
		}
		
		// if no current element is available, remove this listener
		if( current == null ) {
			$(document.body).unbind('mousemove', update);
			return;	
		}
		
		// remove position helper classes
		helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");
		
		var left = helper.parent[0].offsetLeft;
		var top = helper.parent[0].offsetTop;
		if (event) {
			// position the helper 15 pixel to bottom right, starting from mouse position
			left = event.pageX + settings(current).left;
			top = event.pageY + settings(current).top;
			var right='auto';
			if (settings(current).positionLeft) {
				right = $(window).width() - left;
				left = 'auto';
			}
			helper.parent.css({
				left: left,
				right: right,
				top: top
			});
		}
		
		var v = viewport(),
			h = helper.parent[0];
		// check horizontal position
		if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
			left -= h.offsetWidth + 20 + settings(current).left;
			helper.parent.css({left: left + 'px'}).addClass("viewport-right");
		}
		// check vertical position
		if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
			top -= h.offsetHeight + 20 + settings(current).top;
			helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
		}
	}
	
	function viewport() {
		return {
			x: $(window).scrollLeft(),
			y: $(window).scrollTop(),
			cx: $(window).width(),
			cy: $(window).height()
		};
	}
	
	// hide helper and restore added classes and the title
	function hide(event) {
		if($.tooltip.blocked)
			return;
		// clear timeout if possible
		if(tID)
			clearTimeout(tID);
		// no more current element
		current = null;
		
		var tsettings = settings(this);
		function complete() {
			helper.parent.removeClass( tsettings.extraClass ).hide().css("opacity", "");
		}
		if ((!IE || !$.fn.bgiframe) && tsettings.fade) {
			if (helper.parent.is(':animated'))
				helper.parent.stop().fadeTo(tsettings.fade, 0, complete);
			else
				helper.parent.stop().fadeOut(tsettings.fade, complete);
		} else
			complete();
		
		if( settings(this).fixPNG )
			helper.parent.unfixPNG();
	}
	
})(jQuery);

// end jquery/tooltip.js

// jquery/timepicker.js
/*
 * A time picker for jQuery
 * Based on original timePicker by Sam Collet (http://www.texotela.co.uk) -
 * copyright (c) 2006 Sam Collett (http://www.texotela.co.uk)
 *
 * Dual licensed under the MIT and GPL licenses.
 * Copyright (c) 2009 Anders Fajerson
 * @name     timePicker
 * @version  0.2
 * @author   Anders Fajerson (http://perifer.se)
 * @example  $("#mytime").timePicker();
 * @example  $("#mytime").timePicker({step:30, startTime:"15:00", endTime:"18:00"});
 */

(function($){
  $.fn.timePicker = function(options) {
    // Build main options before element iteration
    var settings = $.extend({}, $.fn.timePicker.defaults, options);

    return this.each(function() {
      $.timePicker(this, settings);
    });
  };

  $.timePicker = function (elm, settings) {
    var e = $(elm)[0];
    return e.timePicker || (e.timePicker = new jQuery._timePicker(e, settings));
  };

  $._timePicker = function(elm, settings) {

    var tpOver = false;
    var keyDown = false;
    var startTime = timeToDate(settings.startTime, settings);
    var endTime = timeToDate(settings.endTime, settings);

    $(elm).attr('autocomplete', 'OFF'); // Disable browser autocomplete

    var times = [];
    var time = new Date(startTime); // Create a new date object.
    while(time <= endTime) {
      times[times.length] = formatTime(time, settings);
      time = new Date(time.setMinutes(time.getMinutes() + settings.step));
    }

    var $tpDiv = $('<div class="time-picker'+ (settings.show24Hours ? '' : ' time-picker-12hours') +'"></div>');
    var $tpList = $('<ul></ul>');

    // Build the list.
    for(var i = 0; i < times.length; i++) {
      $tpList.append("<li>" + times[i] + "</li>");
    }
    $tpDiv.append($tpList);
    // Append the timPicker to the body and position it.
    var elmOffset = $(elm).offset();

    //$tpDiv.appendTo('body').css({'top':elmOffset.top, 'left':elmOffset.left}).hide(); // uncomment by kjetil

    // by kjetil - append to target element instead of body, or won't work with modal dialog
    $(elm).wrap("<span class='relative'></span>");
//    $tpDiv.insertAfter(elm).css({'position': 'absolute', 'top': 15, 'left':elmOffset.left}).hide();
    $tpDiv.insertAfter(elm).css({'position': 'absolute', 'top': 15, 'left':0}).hide();
    // end by kjetil
    
    // Store the mouse state, used by the blur event. Use mouseover instead of
    // mousedown since Opera fires blur before mousedown.
    $tpDiv.mouseover(function() {
      tpOver = true;
    }).mouseout(function() {
      tpOver = false;
    });

    $("li", $tpList).mouseover(function() {
      if (!keyDown) {
        $("li.selected", $tpDiv).removeClass("selected");
        $(this).addClass("selected");
      }
    }).mousedown(function() {
       tpOver = true;
    }).click(function() {
      setTimeVal(elm, this, $tpDiv, settings);
      tpOver = false;
    });

    var showPicker = function() {
      if ($tpDiv.is(":visible")) {
        return false;
      }
      $("li", $tpDiv).removeClass("selected");

      // Show picker. This has to be done before scrollTop is set since that
      // can't be done on hidden elements.
      $tpDiv.show();

      // Try to find a time in the list that matches the entered time.
      var time = elm.value ? timeStringToDate(elm.value, settings) : startTime;
      var startMin = startTime.getHours() * 60 + startTime.getMinutes();
      var min = (time.getHours() * 60 + time.getMinutes()) - startMin;
      var steps = Math.round(min / settings.step);
      var roundTime = normaliseTime(new Date(0, 0, 0, 0, (steps * settings.step + startMin), 0));
      roundTime = (startTime < roundTime && roundTime <= endTime) ? roundTime : startTime;
      var $matchedTime = $("li:contains(" + formatTime(roundTime, settings) + ")", $tpDiv);

      if ($matchedTime.length) {
        $matchedTime.addClass("selected");
        // Scroll to matched time.
        $tpDiv[0].scrollTop = $matchedTime[0].offsetTop;
      }
      return true;
    };
    // Attach to click as well as focus so timePicker can be shown again when
    // clicking on the input when it already has focus.
    $(elm).focus(showPicker).click(showPicker);
    // Hide timepicker on blur
    $(elm).blur(function() {
      if (!tpOver) {
        $tpDiv.hide();
      }
    });
    // Keypress doesn't repeat on Safari for non-text keys.
    // Keydown doesn't repeat on Firefox and Opera on Mac.
    // Using kepress for Opera and Firefox and keydown for the rest seems to
    // work with up/down/enter/esc.
    var event = ($.browser.opera || $.browser.mozilla) ? 'keypress' : 'keydown';
    $(elm)[event](function(e) {
      var $selected;
      keyDown = true;
      var top = $tpDiv[0].scrollTop;
      switch (e.keyCode) {
        case 38: // Up arrow.
          // Just show picker if it's hidden.
          if (showPicker()) {
            return false;
          };
          $selected = $("li.selected", $tpList);
          var prev = $selected.prev().addClass("selected")[0];
          if (prev) {
            $selected.removeClass("selected");
            // Scroll item into view.
            if (prev.offsetTop < top) {
              $tpDiv[0].scrollTop = top - prev.offsetHeight;
            }
          }
          else {
            // Loop to next item.
            $selected.removeClass("selected");
            prev = $("li:last", $tpList).addClass("selected")[0];
            $tpDiv[0].scrollTop = prev.offsetTop - prev.offsetHeight;
          }
          return false;
          break;
        case 40: // Down arrow, similar in behaviour to up arrow.
          if (showPicker()) {
            return false;
          };
          $selected = $("li.selected", $tpList);
          var next = $selected.next().addClass("selected")[0];
          if (next) {
            $selected.removeClass("selected");
            if (next.offsetTop + next.offsetHeight > top + $tpDiv[0].offsetHeight) {
              $tpDiv[0].scrollTop = top + next.offsetHeight;
            }
          }
          else {
            $selected.removeClass("selected");
            next = $("li:first", $tpList).addClass("selected")[0];
            $tpDiv[0].scrollTop = 0;
          }
          return false;
          break;
        case 13: // Enter
          if ($tpDiv.is(":visible")) {
            var sel = $("li.selected", $tpList)[0];
            setTimeVal(elm, sel, $tpDiv, settings);
          }
          return false;
          break;
        case 27: // Esc
          $tpDiv.hide();
          return false;
          break;
      }
      return true;
    });
    $(elm).keyup(function(e) {
      keyDown = false;
    });
    // Helper function to get an inputs current time as Date object.
    // Returns a Date object.
    this.getTime = function() {
      return timeStringToDate(elm.value, settings);
    };
    // Helper function to set a time input.
    // Takes a Date object.
    this.setTime = function(time) {
      elm.value = formatTime(normaliseTime(time), settings);
      // Trigger element's change events.
      $(elm).change();
    };

  }; // End fn;

  // Plugin defaults.
  $.fn.timePicker.defaults = {
    step:30,
    startTime: new Date(0, 0, 0, 0, 0, 0),
    endTime: new Date(0, 0, 0, 23, 30, 0),
    separator: ':',
    show24Hours: true
  };

  // Private functions.

  function setTimeVal(elm, sel, $tpDiv, settings) {
    // Update input field
    elm.value = $(sel).text();
    // Trigger element's change events.
    $(elm).change();
    // Keep focus for all but IE (which doesn't like it)
    if (!$.browser.msie) {
      elm.focus();
    }
    // Hide picker
    $tpDiv.hide();
  }

  function formatTime(time, settings) {
    var h = time.getHours();
    var hours = settings.show24Hours ? h : (((h + 11) % 12) + 1);
    var minutes = time.getMinutes();
    return formatNumber(hours) + settings.separator + formatNumber(minutes) + (settings.show24Hours ? '' : ((h < 12) ? ' AM' : ' PM'));
  }

  function formatNumber(value) {
    return (value < 10 ? '0' : '') + value;
  }

  function timeToDate(input, settings) {
    return (typeof input == 'object') ? normaliseTime(input) : timeStringToDate(input, settings);
  }

  function timeStringToDate(input, settings) {
    if (input) {
      var array = input.split(settings.separator);
      var hours = parseFloat(array[0]);
      var minutes = parseFloat(array[1]);

      // Convert AM/PM hour to 24-hour format.
      if (!settings.show24Hours) {
        if (hours === 12 && input.substr('AM') !== -1) {
          hours = 0;
        }
        else if (hours !== 12 && input.indexOf('PM') !== -1) {
          hours += 12;
        }
      }
      var time = new Date(0, 0, 0, hours, minutes, 0);
      return normaliseTime(time);
    }
    return null;
  }

  /* Normalise time object to a common date. */
  function normaliseTime(time) {
    time.setFullYear(2001);
    time.setMonth(0);
    time.setDate(0);
    return time;
  }

})(jQuery);


// end jquery/timepicker.js

// begin searchbar.js

// removed from now - didn't validate
// end searchbar.js

// start googlemap.js

function gmap3_set_marker_image(map_id, marker_id, icon) {
  $("#" + map_id).gmap("find", "markers", {"property": "id", "value": "marker_" + marker_id }, function(gmarker) { // doesnt work as intended
    //alert("looking for =" + marker_id + " id = " + gmarker.id);
    if(gmarker.id == 'marker_' + marker_id) {
      gmarker.setIcon(icon);
      return;
    }
  });
  return null;
}

// returns corresponding gmarker for given marker_id in my set of markers
function gmap3_gmarker2(map_id, marker_id) {
  var $map = $('#' + map_id);
  var gmarkers = $map.data('gmarkers'); 
  var mymarkers = $map.data('markers'); 
  if(gmarkers) {
    $.each(gmarkers, function(i, gmarker) {
      var m = mymarkers[i];
      if(m.id == marker_id) return gmarker;
    });
  }
}

function gmap3_update_list(map_id, prefix) {
  var $map = $('#' + map_id);
  var gmarkers = $map.data('gmarkers'); 
  var mymarkers = $map.data('markers'); 
  if(gmarkers) {
    $.each(gmarkers, function(i, gmarker) {
      var isInViewport = $map.gmap('inViewport', gmarker);
      var m = mymarkers[i];
      if(isInViewport) $('#' + prefix + m.id).show();
      else $('#' + prefix + m.id).hide();        
    });
  }
}

// prints content for gmap infoWindow (text bubble)
function gmap3_marker_content(marker, map_options) {
  var name = '';
  var content = '';
  
  if(is_array(marker)) { // several properties at this location
    var m = marker[0];
    for(var i in marker) {
    	name += gmap3_marker_title(marker[i], map_options) + "<br>";
    }
  } else { // just one property at this locatoin  
    var m = marker;
    name = gmap3_marker_title(marker, map_options) + "<br>";
  }

  content = name;
  //var content = '<b>' + m.name + '</b><br>';

  // use same address for all
  if(m.address) content += m.address + "<br>"; 

  if(m.description) content += '<p>' + m.description + "</p>";
  return content;

}
// var mo = $("#" + ' + map_options.id + '").data("options"); 

// returns the title of the property (often link) used in infoWindow
function gmap3_marker_title(m, map_options) {
  var title = '';
  var name = m.name;
  // alert(dump(map_options));
  if(map_options.select_target) { 
    title += '<a href="#" onclick="var st = $(\'#' + map_options.id + '\').data(\'select_target\'); $(\'#\' + st).val(' + m.id + ');close_parent_dialog(\''+ map_options.id +'\');return false;">' + name + '</a>';
  } else if(m.link) {
    title += '<a href="'+ m.link +'">' + name + '</a>';
  } else {
    title += name;
  }
  return title;
}

function gmap3_loadmarkers(id, markers) {
  var gmarkers = [];
  var mymarkers = [];
  var set_bounds = true;
  var $map = $('#' + id);
  var map_options = $map.data('options');
  if(map_options.center && map_options.accuracy && markers.length == 1) set_bounds = false; // do not auto set bounds
  var hilite_prefix = map_options.hilite;
  var update_list = map_options.update_list;
  var m0; // the first marker
  $.each(markers, function(i, m) {
    var marker_id = i;
    if(is_array(m)) {
      m0 = m[0];
      name = m0.name + " + " + (m.length - 1);
    } else {
      m0 = m;
      name = m0.name;
    }
    var icon = m0.marker ? m0.marker : gmap_icon;
    var icon_hi = m0.marker_hi ? m0.marker_hi : gmap_icon_hi;
    
    var markerOpts = {'id': 'marker_' + marker_id, 'title': name, 'icon': (m0.marker ? m0.marker : gmap_icon), 'position': new google.maps.LatLng(m0.location_lat, m0.location_long), 'bounds': set_bounds };
    if(map_options.radius) {
      var circle_options = {};
      circle_options.center = markerOpts.position;
      circle_options.radius = map_options.radius;
      gmap3_circle(id, circle_options); // don't draw marker, but a circle with approximate location
    } else {
      $map.gmap('addMarker', markerOpts, function(map, gmarker) {
        gmarkers.push(gmarker);
        mymarkers.push(m0);
        $(gmarker).mouseover(function() {
           if(hilite_prefix) gmap3_hilite_item(hilite_prefix, m, true);
           gmarker.setIcon(icon_hi);
        }).mouseout(function() {
          if(hilite_prefix) gmap3_hilite_item(hilite_prefix, m, false);
          gmarker.setIcon(icon);
        });
        var content = gmap3_marker_content(m, map_options);  
        $(gmarker).click(function() {
          $map.gmap('openInfoWindow', {'content': content}, this);
        });
      });
    }
  });

  //var bar1 = $map.data('markers'); 
  //alert(' bar1 count =' + bar1.length + ' marker lenght=' + markers.length );

  $map.data('markers', mymarkers);
  $map.data('gmarkers', gmarkers);    
}

function gmap3_hilite_item(hilite_prefix, marker, hilite) {
  if(is_array(marker)) {
    for(var i in marker) gmap3_hilite_item(hilite_prefix, marker[i], hilite);
  } else {    
    if(hilite) {
      $('#' + hilite_prefix + marker.id).addClass('selected');
    } else {
      $('#' + hilite_prefix + marker.id).removeClass('selected');
    }
  }
}

// new gmap function using API v3 + the jquery gmap plugin from http://code.google.com/p/jquery-ui-map/
function gmap3(id, markers, map_options) {
  var $map = $('#' + id);
  var center = map_options.center ? map_options.center : '0,0';
  var zoom = map_options.zoom || acc2zoom(map_options.accuracy) || 12;
  map_options.id = id;
  var selected_id = map_options.selected_id;
  // alert("zoom = " + zoom);
  // alert("id=" + id + " acc=" + map_options.accuracy + " zoom=" + zoom);
  var hilite_prefix = map_options.hilite;
  var update_list = map_options.update_list;
  $map.data('options', map_options);
  if(map_options.select_target) $map.data('select_target', map_options.select_target); // shortcut
  // if($map.gmap()) $map.gmap('destroy');
  // $map.gmap('clear', 'markers');
  // alert("count=" + markers.length);
  $map.gmap({'center': center, 'zoom': zoom}).bind('init', function(evt, map) {
    //alert('loaded map ' + id);
    if(update_list && hilite_prefix) { // update list of locations to match those in view
//      google.maps.event.addListener(map, 'bounds_changed', function() {
      google.maps.event.addListener(map, 'bounds_changed', function() {
        gmap3_update_list(id,  hilite_prefix);
      });
      google.maps.event.addListener(map, 'zoom_changed', function() {
        var zoom = $map.gmap('option', 'zoom');
      });
    }
    
    gmap3_loadmarkers(id, markers); 
    if(selected_id) gmap3_marker_click(id, selected_id); 

    // begin cut     
// end cut     

  });
}
  
// loop through markers, return marker with given id, or where id is in list
function gmap3_find_marker(markers, id) {
  for(var i in markers) {
    var marker = markers[i];
    if(is_array(marker)) {
      var id_list = i;
      // alert('list=' + id_list);
      //alert("array = " + marker.id);
      //alert(dump(marker));
      for(var j in marker) {
        var m2 = marker[j];
        m2.id_list = i;
        if(m2.id == id) return m2;
        // debug(dump(m2));
        // gmap3_find_marker(m2, id));
        // alert("id=" + id + " IN array = " + m2.id);
        //if(var m = gmap3_find_marker(m2, id)) {
        //  return m;
        //}
      }
    } else {
      // alert(dump(marker));
      if(marker.id == id) return marker;
      // alert("id=" + id + " NOT array = " + marker.id);
      // debug(marker.name + ' is not array, id = ' + marker.id + dump(marker));
      
      //var idAr = marker_id.indexOf(',') ? marker_id.split(',') : [];
      //if(marker_id == id || (idAr.length && in_array(id, idAr))) return marker;
    }
  }
  return null;
}

function gmap3_maplink_init(map_options) {
  var search_marker;
  var id = map_options.id;
  var $map = $('#' + id);
  var accuracy = map_options.accuracy;
  var center = map_options.center;
  $map.data('options', map_options);
  
  // var $map = $("#search_result_map");
  //var map_options = $map.data("options");
  var acc2 = 0;
  $(".map_link").hover(
    function () {
      var id = $(this).attr("id").substr(4);
      var m = markers[id];
      if(!m) m = gmap3_find_marker(markers, id);  
      if(m) {
        var marker_id = m.id_list ? m.id_list : m.id;
        var mymarkers = {id: marker_id};
        $map.show().position({of: $(this), my: "top left", at: "top left", offset: "220 100"});
        gmap3("gmap_popup", {}, {center: center}); // no markers      
        var markerOpts = {"id": "marker_" + m.id, "title": m.name, "icon": m.marker ? m.marker : gmap_icon, "position": new google.maps.LatLng(m.location_lat, m.location_long), "bounds": false };
        $map.gmap("addMarker", markerOpts); // add markers
        gmap3_set_marker_image("search_result_map", marker_id, (m.marker_hi ? m.marker_hi : gmap_icon_hi));
      }
    }, 
    function () {
      var id = $(this).attr("id").substr(4);
      var m = markers[id];
      if(!m) m = gmap3_find_marker(markers, id);
      if(m) {
        var marker_id = m.id_list ? m.id_list : m.id;
        $map.gmap("clear", "markers");
        gmap3_set_marker_image("search_result_map", marker_id, (m.marker ? m.marker : gmap_icon));
        $("#gmap_popup").hide();
      }
    }
  );
}

function gmap3_circle(map_id, options) {
  var $map = $('#' + map_id);
  var circleOptions = {
    strokeColor: "#FF0000",
    strokeOpacity: 0.8,
    strokeWeight: 2,
    fillColor: "#FF0000",
    fillOpacity: 0.35,
    center: options.center,
    radius: options.radius
  };
  $map.gmap('addShape', 'Circle', circleOptions);

}

function boarding_map_init(which_map) {
  var map_id = "boarding_map";
  var $map = $("#" + map_id);
  var my_select_target = which_map == "show_boarding_map" ? "pickup_location" : "dropoff_location";
  $map.data("select_target", my_select_target);

  $( "#map_container" ).dialog({
      width: 650,
      height: 660,
      resizeStop: function(event, ui) {$map.gmap("refresh");},
      close: function(event, ui) {
        // $map.gmap("destroy");
      },
      open: function(event, ui) {
        var selected_id = $("#" + my_select_target).val();
        gmap3(map_id, markers, {"select_target": my_select_target, "selected_id": selected_id});
        if(selected_id) gmap3_marker_click(map_id, selected_id); 
      }
  });                 
}                 

function gmap3_marker_click(map_id, marker_id) {
  $("#" + map_id).gmap("find", "markers", {"property": "id", "value": "marker_" + marker_id }, function(gmarker) { // doesnt work as intended
    if(gmarker.id == "marker_" + marker_id) google.maps.event.trigger(gmarker, "click");
  });
}

    //$map.gmap('microformat', '.vevent', function(result, item, index) {
      // var clone = $(item).clone().addClass('ui-dialog-vevent');
      // clone.append('<div id="streetview{0}" class="streetview"></div>'.replace('{0}', index));
      //var lat = result.location[0].geo[0].latitude['value-title']; 
      //var lng = result.location[0].geo[0].longitude['value-title'];

      // if(map_options.center) { // center and possible accuracy/zoom are specified

      // if(map_options.center) { // center and possible accuracy/zoom are specified
      //   $map.gmap('option', 'center',  map_options.center);
      //   if(map_options.accuracy) $map.gmap('option', 'zoom', acc2zoom(map_options.accuracy));
      //   alert("setting center to " + map_options.center + " and zoom to " + acc2zoom(map_options.accuracy));
      // } else { //determine from markers
      //   var bounds = $map.gmap('get', 'bounds');
      //   $map.gmap('set', 'bounds', bounds);
      // }
      // alert("zoom = " + map_options.zoom);
  //});

function zoom2acc(zoomlevel) {
  if(zoomlevel<=0) return 0;
  if(zoomlevel<=2) return 1;
  if(zoomlevel<=4) return 2;
  if(zoomlevel<=6) return 3;
  if(zoomlevel<=8) return 4;
  if(zoomlevel<=10) return 5;
  if(zoomlevel<=12) return 6;
  if(zoomlevel<=14) return 7;
  return 8;
}

function acc2zoom(accuracy) {
  if(accuracy<=0) return 0;
  if(accuracy==1) return 1;
  if(accuracy==2) return 6;
  if(accuracy==3) return 7;
  if(accuracy==4) return 8;
  if(accuracy==5) return 9;
  if(accuracy==6) return 10;
  if(accuracy==7) return 11;
  return 13;
}

/*
// used to load big map with markers (either apartments or geo locations)
// API version 3 
function loadMap2(mapid, markers, update_list) {
  var i=0;
  if(GBrowserIsCompatible()) {
    var map = new google.maps.Map(document.getElementById(mapid), {
      center: new google.maps.LatLng(47.6145, -122.3418),
      zoom: 13,
      mapTypeId: 'roadmap'
    });
    // var infoWindow = new google.maps.InfoWindow;


    // var map = new google.maps.Map(mapel);
    // map.addControl(new GSmallMapControl());
    // map.addControl(new GMapTypeControl());
    // map.setCenter(new GLatLng(0,0), 13);
    
  } else {
    alert('Your browser is unfortunately not supported by Google Maps');
  }
  var maxzoom = false;
  if(maxzoom) { // for short-term apartments, disable full zoom ?>
    google.maps.event.addListener(map, "zoomend", function (prevlevel, newlevel) {
      if(newlevel > maxzoom) map.setZoom(prevlevel);
   });
  }
      
  var num_markers = markers.length;
  if(num_markers) {
    var min_latitude=1000;
    var max_latitude=-1000;
    var min_longitude=1000;
    var max_longitude=-1000;
    var gmarkers = [];
    // alert("n=" + num_markers);
    for (var i in markers) { // iterate through markers
      var marker = markers[i];
      var name = marker.name;
      var latitude = marker.latitude;
      var longitude = marker.longitude;
      var point = new GLatLng(latitude,longitude);
      var tabs = marker.tabs;
      var accuracy = marker.accuracy;
      var apt_id = marker.id;

      var thelink = marker.link;
      var thelink = thelink.replace(/\&amp;/g,'&'); // remove encoding
      var selected = 0;
    
      var infoTabs = [];

      if(tabs.length) {        
        var infoTabs = [];              
        for (var j in tabs) { // iterate through tabs
          var tab = tabs[j]; 
          infoTabs[j] = new GInfoWindowTab(tab[0], tab[1]);
        }
        var gmarker = createMarker2(point, infoTabs, thelink);
      } else {
        var gmarker = createMarker3(map, point, name, thelink, marker.level, apt_id);
      }
      gmarkers[i] = gmarker;
      alert("pos = " + gmarker.getPosition());
    
      map.addOverlay(gmarker);
      if(selected) gmarker.openInfoWindowTabsHtml(infoTabs);
  
      if(latitude && latitude < min_latitude) min_latitude=latitude;
      if(latitude && latitude > max_latitude) max_latitude=latitude;
      if(longitude && longitude < min_longitude) min_longitude=longitude;
      if(longitude && longitude > max_longitude) max_longitude=longitude;

      //alert("Marker " + i + ": latitude: " + latitude + " longitude: " + longitude + " acc: " + accuracy + " name: " + name + " link:" + thelink);
      //alert("min latitude: " + min_latitude + "max latitude: " + max_latitude + "min longitude: " + min_longitude + "max longitude: " + max_longitude + "avg latitude: " + avg_latitude + "avg longitude: " + avg_longitude);

    }

    // add 10% in x and y
    var diffX = max_longitude-min_longitude;
    var diffY = max_latitude-min_latitude;
    var factor = 0.1;
    var xFactor=diffX*factor;
    var yFactor=diffY*factor;

    min_longitude -= xFactor;
    min_latitude  -= yFactor;
    max_longitude += xFactor;
    max_latitude  += yFactor;
    
    var avg_longitude = (min_longitude + max_longitude) / 2;
    var avg_latitude = (min_latitude + max_latitude) / 2;
  }

  // set center and zoom
  if(num_markers > 1) { 
    var sw = new GLatLng(min_latitude,min_longitude);
    var ne = new GLatLng(max_latitude,max_longitude);
    var avg = new GLatLng(avg_latitude,avg_longitude);
    var bounds = new GLatLngBounds(sw, ne);
    var zoomLevel = map.getBoundsZoomLevel(bounds);
    map.setZoom(zoomLevel);
    map.setCenter(bounds.getCenter());
    //alert('min=min_latitude max=max_longitude many markers: num_markers acc=thisLoc->location_accuracy zoom level ='+zoomLevel);
    map.setCenter(avg);

    var polyline = new GPolyline([
      new GLatLng(min_latitude,min_longitude),
      new GLatLng(min_latitude,max_longitude),
      new GLatLng(max_latitude,max_longitude),
      new GLatLng(max_latitude,min_longitude),
      new GLatLng(min_latitude,min_longitude)
    ], "#ff0000", 2);
    //map.addOverlay(polyline);
  } else if(num_markers==1) { 
    map.setCenter(new GLatLng(latitude,longitude), zoomLevel);
    var zoomLevel = acc2zoom(accuracy);
    map.setZoom(zoomLevel);
    //alert('one markers: num_markers acc=thisLoc->location_accuracy zoom level ='+zoomLevel);
  } else { 
    // use parent location and zoom
    var zoomLevel = acc2zoom(accuracy);
    //alert('no markers: num_markers acc=thisLoc->location_accuracy zoom level ='+zoomLevel);
    map.setCenter(new GLatLng(latitude,longitude), zoomLevel);
  } 
  

  if(update_list) { // dynamically update list to show only items in view
    GEvent.addListener(map, "zoomend", function (prevlevel, newlevel) {
      var vismarkers = gmap_markers_in_view(markers, gmarkers, map);
      alert(dump(vismarkers));
    });
  }
  //alert("min latitude: " + min_latitude + "max latitude: " + max_latitude + "min longitude: " + min_longitude + "max longitude: " + max_longitude + "avg latitude: " + avg_latitude + "avg longitude: " + avg_longitude);
  
  // calculatitudee bounds of markers
  //var zoom2 = acc2zoom(<?=$thisLoc->location_accuracy?>);
  
}  


// load little map
function loadMap(mid, latitude, longitude, accuracy, setmarker) {
  var maxzoom = 0;
  if (GBrowserIsCompatible()) {

    var map = new GMap2(document.getElementById(mid));
    map.enableContinuousZoom();
        
    var zoomlevel=0;
    zoomlevel = acc2zoom(accuracy);
      
    map.addControl(new GSmallMapControl());
    map.addControl(new GMapTypeControl());
    map.setCenter(new GLatLng(latitude,longitude), zoomlevel);
    map.checkResize();
  }
  var point = new GLatLng(latitude,longitude);
  var icon_short = null;

  var themarker = createMarker4(map, point, icon_short, setmarker);
  var markers = [];
  markers.push(themarker);

  var mgrOptions = {maxZoom : 5};

  if(maxzoom) { // for short-term apartments, disable full zoom 
    GEvent.addListener(map, "zoomend", function (prevlevel, newlevel) {
      if(newlevel > maxzoom) map.setZoom(prevlevel);
    });
  } 

  if(setmarker) {
    GEvent.addListener(themarker, "dragstart", function() {
      //map.closeInfoWindow();
    });
    
    GEvent.addListener(themarker, "dragend", function() {
      mpoint = themarker.getPoint();
      document.getElementById('gmap_cont_latitude').value = mpoint.y;
      document.getElementById('gmap_cont_longitude').value = mpoint.x;
      map.zoomIn();
      map.zoomIn();
      map.panTo(mpoint);
      var zoomlevel = map.getZoom();      
      document.getElementById('gmap_cont_accuracy').value = zoom2acc(zoomlevel);
    });

    GEvent.addListener(map, "click", function(marker, point) {
      if (marker) {
        marker.setPoint(point);
      } else {
        themarker.setPoint(point);
        map.panTo(point);
        var zoomlevel = map.getZoom();
        document.getElementById('gmap_cont_accuracy').value = zoom2acc(zoomlevel);
        document.getElementById('gmap_cont_latitude').value = point.y;
        document.getElementById('gmap_cont_longitude').value = point.x;
      }
    });

  }
  map.addOverlay(themarker);
  map.checkResize();
  return map;
}

// call when zooming or panning, function will return array of markers in view 
function gmap_markers_in_view(markers, gmarkers, map) {
  var result = [];
  for (var i=0; i<markers.length; i++){
    if( map.getBounds().contains(gmarkers[i].getPosition()) ){
      result.push(markers[i].id);
    }
  }
  return result;
}

// set values of edit-map
function get_object_map(latitude, longitude, accuracy) {
  $('#gmap_cont_accuracy').val(accuracy); 
  $('#gmap_cont_latitude').val(latitude); 
  $('#gmap_cont_longitude').val(longitude);
}

// copy values from edit-map back to record
function set_object_map(obj_table) {
  var accuracy = $('#gmap_cont_accuracy').val(); 
  var latitude = $('#gmap_cont_latitude').val(); 
  var longitude = $('#gmap_cont_longitude').val();
  
  $('#'+obj_table+'-location_accuracy').val(accuracy); 
  $('#'+obj_table+'-location_lat').val(latitude); 
  $('#'+obj_table+'-location_long').val(longitude);
}

function showMap(parent_id, latitude, longitude, accuracy) {
  $cont = $('#gmap_cont');
  $map = $('#gmap');
  $parent = $('#' + parent_id);  
  $cont.show();
  $map.show();
  $cont.position({of: $parent, my: 'top left', at: 'top left'});
  loadMap('gmap', latitude, longitude, accuracy, false);
}

function showMapEdit(parent_id, latitude, longitude, accuracy) {
	get_object_map(latitude, longitude, accuracy);
  $cont = $('#gmap_cont_edit');
  $map = $('#gmap_edit');
  $parent = $('#' + parent_id);  
  $cont.show();
  $map.show();  
  $cont.position({of: $parent, my: 'top left', at: 'top left'});
  loadMap('gmap_edit', latitude, longitude, accuracy, true);  
}


function createMarker2(point, infoTabs, thelink) {
  var marker = new GMarker(point);
  GEvent.addListener(marker, "mouseover", function() {
    marker.openInfoWindowTabsHtml(infoTabs);
  });
  GEvent.addListener(marker, "click", function() {
    document.location=thelink;
  });
  return marker;
}

function createMarker3(map, point, infoHTML, thelink, level, apt_id) {

  var scale = (8-level)*2;
  // var iconOptions = {};
  // iconOptions.width = 16+scale;
  // iconOptions.height = 16+scale;
  // iconOptions.primaryColor = "#F7BF01";
  // iconOptions.cornerColor = "#3E78A6";
  // iconOptions.strokeColor = "#000000";
  // var cIcon = MapIconMaker.createMarkerIcon(iconOptions);
  var hilite = 'selected';
  var markerImage = '/images/markers/pushpin_red.png';
  var markerImageHilite = '/images/markers/pushpin_yellow.png';

  // Create our "tiny" marker icon
  // var blueIcon = new GIcon(G_DEFAULT_ICON);
  // blueIcon.image = "http://www.google.com/intl/en_us/mapfiles/ms/micons/blue-dot.png";

  var ourIcon = new GIcon(G_DEFAULT_ICON);
  //ourIcon.image = "http://www.google.com/intl/en_us/mapfiles/ms/micons/green-dot.png";
  ourIcon.image = markerImage;
  
  // Set up our GMarkerOptions object
  //markerOptions = {};
  //markerOptions.icon = ourIcon;     
  //markerOptions.title = infoHTML;
  //
  //var marker = new google.maps.Marker(point, markerOptions);
  var marker = new google.maps.Marker({
      map: map,
      position: point,
      icon: ourIcon,
      title: infoHTML,
    });
 
  //var marker = new LabeledMarker(point, {icon: ourIcon, labelText: "A", title: infoHTML});

  // marker.setImage(markerImage);
             
  //GEvent.addListener(marker, "mouseover", function() {
  //  marker.openInfoWindowHtml(infoHTML);
  //});
  google.maps.event.addListener(marker, "click", function() {
    document.location=thelink;
  });

  if(apt_id) {
    google.maps.event.addListener(marker, 'mouseover', function() {
      marker.setImage(markerImageHilite);
      $('#property-' + apt_id).addClass('hilite');
    });
    google.maps.event.addListener(marker, 'mouseout', function() {
      marker.setImage(markerImage);
      $('#property-' + apt_id).removeClass('hilite');
    });
  }

  return marker;
}

function createMarker4(map, point, marker, setmarker) {
  if(setmarker) {
    var marker = new GMarker(point, {draggable: true});
  } else {
    var marker = new GMarker(point);
  }
  return marker;
}


// new google map (API v.3)
function gmap3_load(mapid, markers, map_options) {
  var markerImage = '/images/markers/pushpin_red.png';
  var mapLatlng = new google.maps.LatLng(52.4,4.9); // Amsterdam
  var mapLatlng = new google.maps.LatLng(40, 4);
  var bounds = new google.maps.LatLngBounds();
  var myOptions = {
    zoom: 4,
    center: mapLatlng,
    mapTypeId: google.maps.MapTypeId.ROADMAP,
  }
  var map = new google.maps.Map(document.getElementById(mapid), myOptions);

  if(!markers.length) return map; // no markers, we're done

  var gmarkers = [];
  for (var i in markers) { // iterate through markers
    var marker = markers[i];
    var markerLatlng = new google.maps.LatLng(marker.latitude,marker.longitude);
    var marker_options = {
        position: markerLatlng,
        title: marker.name,
        icon: markerImage,
        id: marker.id
    }
    var gmarker = gmap3_marker(map, marker_options, map_options); // creates the marker object
    gmarker.setMap(map); // To add the marker to the map, call setMap();
    gmarkers.push(gmarker);
    bounds.extend(gmarker.getPosition());
  }
  map.fitBounds(bounds);
  if(!map_options) return map; // no options, we're done

  // process options
  
  if(list_id = map_options.list_id) { // update HTML list to only show items in view
//    google.maps.event.addListener(map, "center_changed", function () {
//    google.maps.event.addListener(map, "center_changed", function () {
//    google.maps.event.addListener(map, "center_changed", function () {
    google.maps.event.addListener(map, "bounds_changed", function () {
      console.log('foo');        
      var vismarkers = gmap_markers_in_view(markers, gmarkers, map);
      debug(vismarkers.length);
    });
  }

  return map;  
}

function gmap3_marker(map, marker_options, map_options) {
  var markerImageHilite = '/images/markers/pushpin_yellow.png';
  var marker = new google.maps.Marker(marker_options);
  if(!map_options) return marker;

                     
  // process options
  item_prefix = map_options.item_prefix;
  if(item_prefix && marker_options.id) { // highlight corresponding item in HTML list
    google.maps.event.addListener(marker, 'mouseover', function() {
      marker.setIcon(markerImageHilite);
      $('#' + item_prefix + marker_options.id).addClass('hilite');
    });                                                   
    google.maps.event.addListener(marker, 'mouseout', function() {
      marker.setIcon(marker_options.icon);
      $('#' + item_prefix + marker_options.id).removeClass('hilite');
    });    
  }

  return marker;
}


*/
// end googlemap.js

// start request.js
function update_pickup(checkin) {
  var $checkbox = $('#airport_pickup');
  var too_late = false;
  
  //var checkin = $('#checkin').val();
  // alert('in=' + checkin);
  if(checkin)  {
    var now = new Date();
    var checkinDate = new Date(sql2date(checkin));
    var deadline = add_days(checkinDate, -1);
    too_late =  now > deadline;
    
    //if(too_late =  now > deadline) { // can't set/change pickup less than 24 hours before check-in
    //  //alert($("#pickup_tip").attr('src'));
    //  //alert($("#pickup_tip").attr('title'));
    //  //$("#pickup_tip").attr({title: 'foo'});
    //}
    //alert("today =" + now + '<br>checkin=' + checkinDate + '<br>deadline=' + deadline + '<br>too_late=' + too_late);
  }
  
  if(!too_late && $('#arrival_method').val()=='air' && $('#arrival_time_disp').val() && $('#arrival_number').val()) {
    $checkbox.attr('disabled', false);
  } else {
    $checkbox.attr('disabled', true);
  }
}

function update_pickup_fee() {
  var checked = $('#airport_pickup').is(':checked');
  var $fee = $('#fee_pickup');  
  $fee.attr('disabled', (checked ? false : true));
  update_overlay_fees(); // only works in calendar...
}
// end request.js

// start property.js

function feedback_update(scores) {
  for(var key in scores) {
    var score = scores[key];
    if(score > 0) {
      $('#feedback_' + key).css('width', scores[key] * 11 - 1);
      $('#feedback_' + key + '_score').html(scores[key]);
      $('#feedback_label_' + key).removeClass('disabled');
    } else { // not rated
      $('#feedback_' + key).css('width', 0);
      $('#feedback_' + key + '_score').html('');
      $('#feedback_label_' + key).addClass('disabled');
    }
  }
  $('#feedback_total').html(scores['overall']);
}

function feedback_load(profile, apt_id, language) {
  //alert(ajax_url);
  var ajax_url = '/home2/ajax/feedback.php?profile=' + profile + '&apt_id=' + apt_id + '&lang=' + language;
  $('#feedback_ind').load(ajax_url);
}  

// end property.js


/*
 * Simple jQuery logger / debugger.
 * Based on: http://jquery.com/plugins/Authoring/
 * See var DEBUG below for turning debugging/logging on and off.
 *
 * @version   20070111
 * @since     2006-07-10
 * @copyright Copyright (c) 2006 Glyphix Studio, Inc. http://www.glyphix.com
 * @author    Brad Brizendine <brizbane@gmail.com>
 * @license   MIT http://www.opensource.org/licenses/mit-license.php
 * @requires  >= jQuery 1.0.3
 */
// global debug switch ... add DEBUG = true; somewhere after jquery.debug.js is loaded to turn debugging on
var DEBUG = true;
// shamelessly ripped off from http://getfirebug.com/
if (!("console" in window) || !("firebug" in console)){
	var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"];
	// create the logging div
	jQuery(document).ready(
		function(){
			// todo: use external window
			// $(document.body).append('<div id="DEBUG"><ol></ol></div>');			
		}
	);
	// attach a function to each of the firebug methods
	window.console = {};
	for (var i = 0; i < names.length; ++i){
		window.console[names[i]] = function(msg){ $('#DEBUG ol').append( '<li>' + msg + '</li>' ); }
	}
}

/**
 * Converts the given data structure to a JSON string.
 * Argument: arr - The data structure that must be converted to JSON
 * Example: var json_string = array2json(['e', {pluribus: 'unum'}]);
 * 			var json = array2json({"success":"Sweet","failure":false,"empty_array":[],"numbers":[1,2,3],"info":{"name":"Binny","site":"http:\/\/www.openjs.com\/"}});
 * http://www.openjs.com/scripts/data/json_encode.php
 */
function array2json(arr) {
    var parts = [];
    var is_list = (Object.prototype.toString.apply(arr) === '[object Array]');

    for(var key in arr) {
    	var value = arr[key];
        if(typeof value == "object") { //Custom handling for arrays
            if(is_list) parts.push(array2json(value)); /* :RECURSION: */
            else parts[key] = array2json(value); /* :RECURSION: */
        } else {
            var str = "";
            if(!is_list) str = '"' + key + '":';

            //Custom handling for multiple data types
            if(typeof value == "number") str += value; //Numbers
            else if(value === false) str += 'false'; //The booleans
            else if(value === true) str += 'true';
            else str += '"' + value + '"'; //All other things
            // :TODO: Is there any more datatype we should be in the lookout for? (Functions?)

            parts.push(str);
        }
    }
    var json = parts.join(",");
    
    if(is_list) return '[' + json + ']';//Return numerical JSON
    return '{' + json + '}';//Return associative JSON
}

function create_file_uploader(input_id, target, attr, allowed_extensions, size_limit, allow_multiple, success_handler, upload_dir, mediaData, resizeData) {
  // if (typeof upload_dir === 'undefined') {
  //   alert(upload_dir);
  //   upload_dir = '';
  // }
  var uploader = new qq.FileUploader({

    // container element DOM node (ex. $(selector)[0] for jQuery users)
    element: $('#' + input_id + '-uploader')[0],
    //element: document.getElementById(id + '-uploader'),
            
    debug: true,
    action: '/admin/app_data.php',
    params: {
        param1: upload_dir,
        param2: mediaData
    },
    button: null,
    multiple: true,
    maxConnections: 3,
    allowedExtensions: allowed_extensions,        
    sizeLimit: size_limit,
    minSizeLimit: 0,                             
    onSubmit: function(id, fileName){},
    onProgress: function(id, fileName, loaded, total){},
    onCancel: function(id, fileName){},
    onComplete: function(id, fileName, responseJSON) {
      // var allow_multiple = ".($allow_multiple ? 'true' : 'false').";
      // alert(dump(responseJSON));
      var error = responseJSON.error;
      var success = responseJSON.success == 1;
      var path = responseJSON.path;
      var src = path && fileName ? path + fileName : '';      
      if(success && src) {
        var $input = $('#' + input_id);
        var val = $input.val();
        var target_val = attr == 'background-image' ? "url('" + src + "')" : src; 
        var id = responseJSON.id;
        //var $target = $input.data('target');
        var $target = $g_target;
        if(!$target.length && target) $target = $(target);  
        if($target.length && attr) $target.css(attr, target_val);
          //alert("input_id=" + input_id + " orgval =" + $input.data('orgval') + " target=" + target + " $target id=" + $target.attr('id')); // target = " + $('#' + input_id).data('target'));
          //var $target = target ? $(target) : $('#' + input_id).data('target');
          // var camel_attr = attr.toCamel;
          // camel_attr = "backgroundImage";
          // alert("camel of " + attr + " = " + camel_attr);
          // $target.attr('backgroundColor', '');
          // alert('Upload completed. id= ' + input_id + ' ' + camel_attr + ' of ' + target + ' = ' + $(target).attr(camel_attr) + ' path=' + path + ' src=' + src);
          // alert($target.attr('id') + ' = ' + $target.attr('backgroundImage')); 
        if(success_handler) {  // function name
          var funcCall = success_handler  + "(responseJSON);";
          eval(funcCall);
        }

        // if(onComplete) eval(onComplete); // code

        if(val && allow_multiple) { // append
          // alert(allow_multiple);
          $input.val(val + ',' + target_val);
        } else { // overwrite
          $input.val(target_val);
        }
        // if(error) alert("Upload completed, but with the following error: " + error);
      } else {
        // if(error) alert("Upload failed with following error: " + error);
      }
      // alert('Upload completed. id=' + id + ' filename=' + fileName + ' to ' + path + ' success=' + success + ' error=' + error + ' target=' + target + ' attr=' + attr);
    },
    messages: {
      typeError: '{file} has invalid extension. Only {extensions} are allowed.',
      sizeError: '{file} is too large, maximum file size is {sizeLimit}.',
      minSizeError: '{file} is too small, minimum file size is {minSizeLimit}.',
      emptyError: '{file} is empty, please select files again without it.',
      onLeave: 'The files are being uploaded, if you leave now the upload will be cancelled.'            
    },
    showMessage: function(message){
      alert(message);
    }
  });
  return uploader;
}
                                
function CKFinder_BrowseServer(input_id) {                                                                                                                                                       
	var finder = new CKFinder();
	finder.BasePath = '/ckfinder/' ;
	finder.selectActionFunction = CKFinder_SetFileField;
	//finder.SelectFunctionData = input_id + '|' + target_id ;
	finder.selectActionData = input_id;
	finder.popup() ;
}
 

// This is a sample function which is called when a file is selected in CKFinder.
function CKFinder_SetFileField(fileUrl, data) {
  if(g_userid) fileUrl = fileUrl.replace('/user/', '/user/' + g_userid + '/');
  var input_id =  data["selectActionData"];
  var target_val = input_id == 'background-image' ? "url('" + fileUrl + "')" : fileUrl;   
	var remote = $(window.opener).length == 1;
                                                                                                  
	var $input_field = $('#' + input_id);
  var size = data['fileSize'];
  var nameAr = fileUrl.split('/');
  var name = nameAr[nameAr.length-1];
  if($g_target) $g_target.css(input_id, target_val);
  $input_field.val(target_val);
  $('#background-image-uploader UL').html('<li class="qq-upload-success"><span class="qq-upload-file">' + name + '</span><span style="display: inline;" class="qq-upload-size">' + size + 'kB</span><span class="qq-upload-failed-text">Failed</span></li>');
  layout_changed();
}

/* begin CMS */
var uploader = 0;
var g_dir_array = ['top', 'right', 'bottom', 'left'];
var g_css_changed = false;   
var g_divs_onscreen = new Array;
var g_div_edited = '';
var g_selector = 0;
var $g_target = 0;
var g_dir_selectors = new Array;

var g_css_selectors = [
                       {'tab': 'Dimensions', 'label': 'Width',       'name': 'width',                 'type': 'slider', 'max': 1000, 'unit': 'px'},
                       {'tab': 'Dimensions', 'label': 'Height',      'name': 'height',                'type': 'slider', 'max': 1000, 'orientation': 'horizontal', 'unit': 'px'},
                       {'tab': 'Dimensions', 'label': 'Margin',      'name': 'margin',                'type': 'slider', 'min': -50, 'max': 50, 'unit': 'px', 'directional' : true},
                       {'tab': 'Dimensions', 'label': 'Padding',     'name': 'padding',               'type': 'slider', 'max': 50, 'unit': 'px', 'directional' : true},
                                                                     
                       {'tab': 'Position',   'label': 'Position',    'name': 'position',              'type': 'select', 'values': ['', 'absolute', 'relative', 'fixed', 'static', 'inherit']},
                       {'tab': 'Position',   'label': 'Left',        'name': 'left',                  'type': 'slider', 'max': 500, 'min': -500, 'unit': 'px'},
                       {'tab': 'Position',   'label': 'Top',         'name': 'top',                   'type': 'slider', 'max': 500, 'min': -500, 'orientation': 'horizontal', 'unit': 'px'},
                       {'tab': 'Position',   'label': 'Bottom',      'name': 'bottom',                'type': 'slider', 'max': 500, 'min': -500, 'orientation': 'horizontal', 'unit': 'px'},
                       {'tab': 'Position',   'label': 'Right',       'name': 'right',                 'type': 'slider', 'max': 500, 'min': -500, 'orientation': 'horizontal', 'unit': 'px'},
                       {'tab': 'Position',   'label': 'Overflow',    'name': 'overflow',              'type': 'select', 'values': ['', 'visible', 'hidden', 'scroll', 'auto', 'inherit']},
                       {'tab': 'Position',   'label': 'Clear',       'name': 'clear',                 'type': 'select', 'values': ['', 'left', 'right', 'both', 'none', 'inherit']},
                       {'tab': 'Position',   'label': 'Visibility',  'name': 'visibility',            'type': 'select', 'values': ['', 'visible', 'hidden', 'collapse', 'inherit']},
                       {'tab': 'Position',   'label': 'Cursor',      'name': 'cursor',                'type': 'select', 'values': ['', 'auto', 'default', 'crosshair', 'help', 'move', 'pointer', 'progress', 'text', 'wait', 'e-resize', 'n-resize', 's-resize', 'e-resize', 'w-resize', 'ne-resize', 'nw-resize', 'se-resize', 'sw-resize', 'inherit' ]},
                       {'tab': 'Position',   'label': 'Display',     'name': 'display',               'type': 'select', 'values': ['', 'none', 'block', 'inline', 'inline-block', 'inline-table', 'list-item', 'table', 'table-caption','table-cell','table-column','table-column-group','table-footer-group','table-header-group','table-row', 'table-row-group','inherit']},
                       {'tab': 'Position',   'label': 'Z-Index',     'name': 'z-index',               'type': 'slider', 'max': 1000, 'min': -1000, 'unit': ''},
                                                                     
                       {'tab': 'Border',     'label': 'Color',       'name': 'border-color',          'type': 'color', 'directional' : true, 'size': 6},
                       {'tab': 'Border',     'label': 'Style',       'name': 'border-style',          'type': 'select', 'directional' : true, 'values': ['', 'none', 'solid', 'dotted', 'dashed', 'double', 'groove', 'ridge', 'inset', 'outset'], 'size': 6},
                       {'tab': 'Border',     'label': 'Width',       'name': 'border-width',          'type': 'slider', 'max': 20, 'unit': 'px', 'directional' : true, 'size': 6},

                       {'tab': 'Outline',    'label': 'Color',       'name': 'outline-color',          'type': 'color', 'directional' : false, 'size': 6},
                       {'tab': 'Outline',    'label': 'Style',       'name': 'outline-style',          'type': 'select', 'directional' : false, 'values': ['', 'none', 'solid', 'dotted', 'dashed', 'double', 'groove', 'ridge', 'inset', 'outset'], 'size': 6},
                       {'tab': 'Outline',    'label': 'Width',       'name': 'outline-width',          'type': 'slider', 'max': 20, 'unit': 'px', 'directional' : false, 'size': 6},
                                                                     
                       {'tab': 'Background', 'label': 'Color',       'name': 'background-color',      'type': 'color', 'size': 6},
                       {'tab': 'Background', 'label': 'Repeat',      'name': 'background-repeat',     'type': 'select', 'values': ['', 'no-repeat', 'repeat', 'repeat-x', 'repeat-y', 'inherit']},
                       {'tab': 'Background', 'label': 'Attachment',  'name': 'background-attachment', 'type': 'select', 'values': ['','scroll','fixed','inherit']},
                       {'tab': 'Background', 'label': 'Position',    'name': 'bg-position-select',    'type': 'select', 'altfield': 'background-position', 'keyvalues': ['', '', '50% 50%', 'center', '0% 50%', 'left', '100% 50%', 'right', '0% 0%', 'top left', '50% 0%', 'top', '100% 0%', 'top right', '0% 100%', 'bottom left', '50% 100%', 'bottom', '100% 100%', 'bottom right']},
                       {'tab': 'Background', 'label': 'Image',       'name': 'background-image',      'type': 'upload'},
  
                       {'tab': 'Text',       'label': 'Color',          'name': 'color',                 'type': 'color', 'size': 6},
                       {'tab': 'Text',       'label': 'Decoration',     'name': 'text-decoration',       'type': 'select', 'values': ['', 'none', 'underline', 'overline', 'line-through', 'blink', 'inherit']},
                       {'tab': 'Text',       'label': 'Weight',         'name': 'font-weight',           'type': 'select', 'values': ['', 'normal', 'bold', 'bolder', 'lighter', '100', '200', '300', '400', '500', '600', '700' , '800' ,'900']},
                       {'tab': 'Text',       'label': 'Style',          'name': 'font-style',            'type': 'select', 'values': ['', 'normal', 'italic', 'oblique']},
                       {'tab': 'Text',       'label': 'Font',           'name': 'font-family',           'type': 'select', 'keyvalues': ['Verdana, Geneva, sans-serif', 'Verdana', '"Trebuchet MS", Helvetica, sans-serif', 'Trebucht', '"Times New Roman", Times, serif', 'Times New Roman', 'Tahoma, Geneva, sans-serif', 'Tahoma', '"Palatino Linotype", "Book Antiqua", Palatino, serif', 'Palatino', '"Lucida Console", Monaco, monospace', 'Lucida Console', '"Lucida Sans Unicode", "Lucida Grande", sans-serif', 'Lucida', 'Impact, Charcoal, sans-serif', 'Impact', 'Georgia, serif', 'Georgia', '"Courier New", Courier, monospace', 'Courier New', '"Comic Sans MS", cursive, sans-serif', 'Comic Sans MS', 'Arial Black, Gadget, sans-serif', 'Arial Black', 'Arial, Helvetica, sans-serif', 'Arial']},
                       {'tab': 'Text',       'label': 'Size',           'name': 'font-size',             'type': 'slider', 'max': 50, 'unit': 'px'},
                       {'tab': 'Text',       'label': 'Line Height',    'name': 'line-height',           'type': 'slider', 'max': 50, 'unit': '', 'step': 0.1},
                       {'tab': 'Text',       'label': 'Letter Spacing', 'name': 'letter-spacing',        'type': 'slider', 'max': 50, 'unit': 'px', 'step': 0.1},
                       {'tab': 'Text',       'label': 'Word Spacing',   'name': 'word-spacing',          'type': 'slider', 'max': 50, 'unit': 'px', 'step': 0.1},
                       {'tab': 'Text',       'label': 'Indent',         'name': 'text-indent',           'type': 'slider', 'max': 50, 'unit': 'px', 'step': 0.1},                                                                                                            
                       {'tab': 'Text',       'label': 'H Align',        'name': 'text-align',            'type': 'select', 'values': ['', 'left', 'right', 'center', 'justify', 'inherit']},
                       {'tab': 'Text',       'label': 'V Align',        'name': 'vertical-align',        'type': 'select', 'values': ['', 'baseline', 'top', 'middle', 'bottom', 'sub', 'super', 'text-top', 'text-bottom', 'inherit']},
                       {'tab': 'Text',       'label': 'Transform',      'name': 'text-transform',        'type': 'select', 'values': ['', 'none', 'capitalize', 'uppercase', 'lowercase', 'inherit']},
                       {'tab': 'Text',       'label': 'White space',    'name': 'white-space',           'type': 'select', 'values': ['', 'normal', 'nowrap', 'pre', 'pre-line', 'pre-wrap', 'inherit']},
                       {'tab': 'Text',       'label': 'Direction',      'name': 'direction',             'type': 'select', 'keyvalues': ['', '', 'ltr', 'Left-to-right', 'rtl', 'Right-to-left', 'inherit', 'inherit']},

                       {'tab': 'List',       'label': 'Image',       'name': 'list-style-image',      'type': 'upload'},
                       {'tab': 'List',       'label': 'Position',    'name': 'list-style-position',   'type': 'select', 'values': ['', 'inside', 'outside', 'inherit']},
                       {'tab': 'List',       'label': 'Style',       'name': 'list-style-type',       'type': 'select', 'values': ['', 'none', 'circle', 'disc', 'square', 'armenian', 'decimal', 'decimal-leading-zero', 'georgian', 'lower-alpha', 'lower-greek', 'lower-latin', 'lower-roman', 'upper-alpha', 'upper-latin', 'upper-roman', 'inherit']},  
  
                       {'tab': 'Opacity',    'label': 'Opacity',        'name': 'opacity',               'type': 'slider', 'max': 1, 'step': 0.1, 'unit': ''},
                       
                      ]; // [{"id":"12","unique":"1","name":"layout-title","description":null}, {"id":"12","unique":"1","name":"layout-title","description":null},]


// creates form + accordion 
function layout_init(db_divs_json) {
  var db_divs = eval(db_divs_json);
  var $panel = $('#page_layout_panel');
  var $form = $('#layout_form');
  layout_select($('#layout_div_select'), db_divs);
                                                   
  // create accordion                                             
  var accordion = '';
  var accordionAr = new Array;
  for( var i = 0; i < g_css_selectors.length; i++ ) {
    var css_selector = g_css_selectors[i];    
    var selector_html = layout_selector(css_selector);
    accordionAr[css_selector.tab] = accordionAr[css_selector.tab] ? accordionAr[css_selector.tab] + selector_html : selector_html;
  }
          
  for(var tab in  accordionAr) accordion += "<h3><a href='#'>" + tab + "</a></h3><div>" + accordionAr[tab] + "</div>";
  
  $form.append("<div id='layout-accordion'>" + accordion + "</div>");

  layout_selectors_init(g_css_selectors); // binds 
  layout_selectors_init(g_dir_selectors); // binds 
  
  $('#page_id').bind('change', function() {
    var $option = $("#page_id option:selected");   
    var link = $option.attr('title');
    layout_select_page(this.value, link);
  });    
}

// $css_form['dimensions'] .= html_div(html_label('Width:', 'width').form_input('width', 'text', '', 6).html_div('','slider','id="width-slider"'));
  //                                               
  // $css_form['position'] .= html_div(html_label('Position:', 'position').select_from_array('position', $position_array));
  // $css_form['border'] .= html_div(form_input('border-color', 'text', '', 5, 0, '', 'colorpicker_input'));
  // $css_form['background'] .= html_div(form_input('background-image', 'text', '', 20, 0, '', '').html_div('', '', 'id="background-image-uploader"'));  

// returns a select box with given name and values
// if associate is set, 1st value is key, 2nd value is value etc
function html_select_box(name, values, associative, selected) {
  var options = '';
  if(associative) {
    for( var i = 0; i < values.length; i+=2 ) {
      var key = values[i];
      var value = values[i+1];
      var selected_str = selected == key ? " selected='selected'" : '';   
      options += "<option value='" + key + "'" + selected_str + ">" + value + "</option>\n";
    }
  } else {
    for( var i = 0; i < values.length; i++ ) {
      var value = values[i];  
      var selected_str = selected == value ? " selected='selected'" : '';   
      options += "<option value='" + value + "'" + selected_str + ">" + value + "</option>\n";
    }
  }
  return "<select name='" + name + "' id='" + name + "'>" + options + "</select>";
}
  
// creates the HTML placeholder code for selectors/widgets (sliders, colorpicker, select boxes etc)
function layout_selector(css_selector) {
  var name = css_selector.name;
  var output = "<div><label for='" + name + "'>" + css_selector.label + ":</label>";
  var cb = css_selector.directional ? " <input name='" + name + "-directional' id='" + name + "-directional'  type='checkbox'   /> " + css_selector.label + " per side" : "";

  switch(css_selector.type) {     
    case 'color':
      output += "<input name='" + name + "' id='" + name + "' type='text' value='' size='5' class='colorpicker_input' />" + cb;
      break;
    case 'slider':     
      output += "<input name='" + name + "' id='" + name + "' type='text' value='' size='6'/>" + cb + "<div class='slider' id='" + name + "-slider' ></div>";
      break;
    case 'select':
      if(values = css_selector.values) {
        output += html_select_box(name, css_selector.values, false) + cb;
      } else if(values = css_selector.keyvalues) {
        output += html_select_box(name, css_selector.keyvalues, true) + cb;
      }
      break;
    case 'upload':
      var g_target = 'layout-left';
      // create_file_uploader(id, target, attr, allowed_extensions, size_limit, allow_multiple); 
      output += "<input name='" + name + "' id='" + name + "' type='text' value='' size='20' /><div id='" + name + "-uploader' ></div>";
      // output += "<a href='/admin/ckfinder.php?tf=" + name + "&te=" + g_target + "' target='_new'>Browse Server</a>"
      // output += "<a href='javascript:CKFinder_BrowseServer(\"" + name + "\")'>Browse Server</a>"
      output += "<div class='qq-upload-button browse-button' onclick='CKFinder_BrowseServer(\"" + name + "\");'>Browse the server</div>";


      break;
    default:
      break;
  }
  if(af = css_selector.altfield) output += "<input name='" + af + "' id='" + af + "' type='text' value='' size='10'/>";
  if(css_selector.directional) {  
    var dir_selectors = '';
    var css_selectors = new Array(css_selector, css_selector, css_selector, css_selector);
    css_selectors = eval(array2json(css_selectors)); // clone                       
    for(var i = 0; i < g_dir_array.length; i++) {
      var dir = g_dir_array[i];    
      css_selectors[i].parent = css_selector.name;
      css_selectors[i].label = dir.ucfirst() + " " + css_selector.label;
      css_selectors[i].values = css_selector.values; 
      css_selectors[i].keyvalues = css_selector.keyvalues;
      css_selectors[i].name = layout_directional_id(css_selector.name, dir);
      css_selectors[i].directional = false;
      dir_selectors += layout_selector(css_selectors[i]);
      
    }
    g_dir_selectors = g_dir_selectors.concat(css_selectors); 
    output += '<div id="' + name + '-dir_controls">' + dir_selectors  + '</div>'                     
    //layout_selectors_init(css_selectors);
    //return;
  }
  output += "</div>";
  return output;
}  

//function layout_dir_selector(parent

// create custom selectors/widgets (sliders, colorpicker, select boxes etc)
// bind change/hover functions to input elements
function layout_selectors_init(css_selectors) {           
  for( var i = 0; i < css_selectors.length; i++ ) {
    css_selector = css_selectors[i];  
    var $input = $("#" + css_selector.name);
    $input.data('css_selector', css_selector); // store selector with input
    if(css_selector.directional) {
      //var input_id = css_selector.name;
      //var unit = css_selector.unit;
      var $cb = $input.parent().find(':checkbox');
      $cb.data('css_selector', css_selector);
      $cb.bind('change', function () {layout_direction_update($(this).data('css_selector'), true);});
    }             
                                                                                                             
    switch(css_selector.type) {
      case 'color':
        layout_color_picker(css_selector);
        break;
      case 'slider':                            
        layout_slider(css_selector); 
        break;
      case 'select':
        layout_select_box(css_selector);
        break;
      case 'upload':
        // create_file_uploader(id, target, attr, allowed_extensions, size_limit, allow_multiple); 
        uploader = create_file_uploader('background-image', '', 'background-image', ['jpg', 'gif', 'png', 'jpeg'], 0, false, 'layout_changed();'); 
        break;
      default:
        break;
    }
    //if(css_selector.directional) layout_directional_inputs(css_selector);
  }
}  



// populates the layout selector with divs that actually exist on page
function layout_select($parent, db_divs) {
  var sel = '<select name="div_select" id="div_select" class="filter">' + "\n" +
            '  <option value="0">Select Element...</option>';  
  for( var i = 0; i < db_divs.length; i++ ) {
    var divObj = db_divs[i];
    var selector = divObj.name; 
    if($(selector).length) sel += '<option onmouseover="layout_hover(\'' + selector + '\'); " value="'+ selector + '">' + selector +'</option>';
  }
  sel += "</select>\n";
  $parent.append(sel);
  $('#div_select').change(function() {
    layout_select_div(this.value);
  });
}

function layout_select_page(page_id, link) { 
  var remote = $(window.opener).length == 1;
  if(remote) window.opener.location = link;
  else window.location = link;
  $('#div_select').val(0);
  layout_select_div(0);
}

function layout_select_div(selector) {
  g_selector = selector;

  //alert(selector);
  var $css_panel = $('#layout-accordion');
  //$css_panel.css('left', '0px'); // show the accordion

  if(g_div_edited) {
    $(g_div_edited).resizable('destroy');
    $(g_div_edited).draggable('destroy');
  }
  
  if(selector && selector != 0) {
    $css_panel.css('left', '0px');
    $css_panel.accordion();      
  } else {
    $g_target = 0;
    $css_panel.css('left', '-1000px');
    return;
  }         
  g_div_edited = selector;


  var remote = $(window.opener).length == 1;
  var $target = $g_target = remote ? window.opener.$(selector) : $(selector);
  layout_save_original($target, g_css_selectors);
  //alert("target=" + $target.attr('id'));
  //layout_reset();
  $target.resizable({
     resize: function(event, ui) {
       var w = ui.size.width;
       var h = ui.size.height;
       var unit = 'px'; // todo: allow others?
       $('#width').val(w + unit);
       $('#height').val(h + unit);
       $('#width-slider').slider('value', w);
       $('#height-slider').slider('value', h);
       layout_changed();
       $('#layout-accordion').accordion( "activate", 0);
     },
     stop: function(event, ui) {
     }
  });                                                                                 
  $target.draggable({
     drag: function(event, ui) {
       var top = ui.position.top;
       var left = ui.position.left;
       var unit = 'px'; // todo: allow others?
       $('#top').val(top + unit);
       $('#left').val(left + unit);
       $('#top-slider').slider('value', top);
       $('#left-slider').slider('value', left);
       layout_changed();
       $('#layout-accordion').accordion( "activate", 1);
     },
     stop: function(event, ui) {
     }
  });
  layout_hover(selector);
}

// sets value and bg-color of fld to hex , fg-color to black or white depending on brightness - used by color_picker
function set_color(fld, hex) {
  var bg = hex ? hex : 'FFFFFF'; 
  if(!hex) hex = '';
  var $el = $('#' + fld);
  $el.val(hex);
  var brightness = hex ? color_brightness(hex) : 1;
  var fg = brightness < 0.5 ? '#FFFFFF' : '#000000';
  $el.css('color', fg);
  $el.css('background-color', '#' + bg);
}

function layout_reset() {
  var $selected = $("#div_select option:selected"); 
  var val  = $selected.text();
  var remote = $(window.opener).length == 1;
  var $target = remote ? window.opener.$(val) : $(val);

  g_css_changed = false;
  // alert('selected=' + val);
  // restore original values on cancel
  for( var i = 0; i < g_css_selectors.length; i++ ) {
    var css_selector = g_css_selectors[i];    
    var css_property = css_selector.target ? css_selector.target : css_selector.name;
  
    var org_val = $('#' + css_selector.name).data('orgval');
    switch(css_selector.type) {
      case 'color':
        if(!org_val) org_val = '';
        // alert("org " + css_selector.name + " of " + val + " is " + org_val);
        // alert("setting color of " + css_selector.name + " to " + org_val);
        $target.css(css_selector.name, '#' + org_val);
        set_color(css_selector.name, org_val);
        break;
      case 'slider':
        $('#' + css_selector.name).val(org_val);
        $('#' + css_selector.name+ '-slider').slider('value', parseInt(org_val));
        $target.css(css_selector.name, org_val);
        break;
      case 'select':
        $('#' + css_selector.name).val(org_val);
        if(css_selector.target) {
          //alert("resetting " + css_selector.target + " to " + org_val);
          $('#' + css_selector.target).val(org_val);
        }
        $target.css(css_property, org_val);
        break;
      default:
        $('#' + css_selector.name).val(org_val);
        $target.css(css_property, org_val);
        break;
    }
    if(css_selector.directional) {
      var $dir_input = $('#' + css_selector.name + '-directional');
      $dir_input.attr('checked', $dir_input.data('orgval'));
      layout_direction_update(css_selector, false);
    }
  }
  $("#page_id").attr('disabled', false);
  $("#div_select").attr('disabled', false);
  $("#css_save").attr('disabled', true);
  $("#css_cancel").attr('disabled', true);  
  //alert("enabled select disabled=" + $("#div_select").attr('disabled') + " id=" + $("#div_select").attr('id'));
}

function layout_hover(selector) {
  var remote = $(window.opener).length == 1;
  var $target = remote ? window.opener.$(selector) : $(selector);
  for( var i = 0; i < g_css_selectors.length; i++ ) {
    var css_selector = g_css_selectors[i];
    var val = layout_css_read($target, css_selector);
    layout_set_selector(css_selector, val);
    val_arr = val.split(' ');
    if(css_selector.directional) {
      $('#' + css_selector.name + '-directional').attr('checked', val_arr.length == 4 ? true : false);
      layout_direction_update(css_selector, false);
    }
  }
  // $target.effect('highlight', {}, 500);
}

function layout_set_selector(css_selector, val) {
  switch(css_selector.type) {                          
    case 'color':
      set_color(css_selector.name, val);
      break;
    case 'upload':
      // alert("setting " + css_selector.name + " to " + $target.css(css_selector.name));
      $('#' + css_selector.name).val(val);
      break;
    case 'select':
      $('#' + css_selector.name).val(val);
      if(altfield = css_selector.altfield) {
        // alert("Setting " + altfield + " to " + val);
        //$target.css(altfield, value); // update target css
        $('#' +altfield).val(val); // write to alt input
      }
      break;
    case 'slider':
      var intVal = parseInt(val);
      var $slider = $('#' + css_selector.name+ '-slider');
      $('#' + css_selector.name).val(val);
      $slider.slider('value', intVal);

      // var max = Math.max(intVal * 2, css_selector.max);
      // var min = Math.min(intVal * 2, css_selector.min);
      // $slider.slider('option', 'max', max);
      // $slider.slider('option', 'min', min);
      // $('#' + css_selector.name+ '-slider').slider('value', val);
      break;
    default:
      $('#' + css_selector.name).val(val);
      break;
  }
}
  
function layout_direction_join(css_selector) {
  var parent_id = css_selector.parent;
  var $parent = $('#' + parent_id);
  //var parent_id = $parent.attr('id');
  var val_array = new Array();
  for(var i = 0; i < g_dir_array.length; i++) {
    var dir = g_dir_array[i];    
    var dir_id = layout_directional_id(parent_id, dir);
    val_array[i] = $('#' + dir_id).val();
  }
  var value = val_array.join(' ');
  // alert(value);
  $parent.val(value);

  var $target = $parent.data('target');
  //alert("val=" + value);
  return value;
}
                                                                   
function layout_direction_update(css_selector, update) {
  var input_id = css_selector.name;
  var unit = css_selector.unit;
  var $input = $('#' + input_id);
  var checked = $('#' + input_id + '-directional').attr('checked');
  var type = $input.attr('type');

  var $parent = css_selector.type == 'slider' ? $('#' + input_id + '-slider') : $input;
  var parent_val = $input.val();
  var val_array = parent_val ? parent_val.split(' ') : [];
  var first_val = val_array.length==4 && val_array[0] ? val_array[0] : '';
  // var css_selector = $input.data('css_selector');
  
  if(checked) {
    if(type == 'text') $input.attr('size', 28);
    if(css_selector.type == 'color') $input.removeClass('colorpicker_input');
    else if(css_selector.type == 'select') {
      $input.replaceWith("<input name='" + $input.attr('id') + "' id='" + $input.attr('id') + "' type='text' size='28' value='" + $input.val() + "'>");
      $input = $('#' + input_id); // reload
    } else if(css_selector.type == 'slider') {
      $('#' + input_id + '-slider').hide();
    }

    $('#' + input_id + '-dir_controls').show();

    for(var i = 0; i < g_dir_array.length; i++) {
      var dir = g_dir_array[i];    
      var dir_id = layout_directional_id(input_id, dir);
      var $dir_input = $('#' + dir_id);
      var css_dir_selector = $dir_input.data('css_selector');
      var dir_val = $dir_input.val();
      if(!dir_val) {
        dir_val = val_array.length==4 ? val_array[i] : parent_val;
        layout_set_selector(css_dir_selector, dir_val);
      }
    }       
    layout_direction_join(css_dir_selector);
    $input.hide();
        
  } else {
    if(update && first_val) { // user just unchecked the box. Set value to first of four
      parent_val = first_val;
      $input.val(first_val);    
    }

    if(!update) { // hover or reset - unchecked. clear all directional values
      for(var i = 0; i < g_dir_array.length; i++) {
        var dir = g_dir_array[i];    
        var dir_id = layout_directional_id(input_id, dir);
        var $dir_input = $('#' + dir_id);
        $dir_input.val('');
      }       
    }
    
    $input.show();
    $('#' + input_id + '-dir_controls').hide();
    if(type == 'text') $input.attr('size', 7);
    if(css_selector.type == 'color') {
      $input.removeClass('colorpicker_input');
    } else if(css_selector.type == 'select' && type == 'text') {
      if(css_selector.values) {
        var selectbox = html_select_box(css_selector.name, css_selector.values, false, parent_val);
      } else if(css_selector.keyvalues) {
        var selectbox = html_select_box(css_selector.name, css_selector.keyvalues, true, parent_val);
      }
      $input.replaceWith(selectbox);
      $input = $('#' + input_id); // reload
    } else if(css_selector.type == 'slider') {
      $('#' + input_id + '-slider').show();
    }
  }
  if($g_target && update) layout_css_write($g_target, css_selector, $input.val());
}
   
function layout_directional_id(input_id, dir) {
  var id_arr = input_id.split('-');
  return id_arr.length > 1 ? id_arr[0] + '-' + dir + '-' + id_arr[1] : input_id + '-' + dir;
}

function layout_css_write($target, css_selector, value) {
  if(css_selector.type == 'color') { // prepend # to colors
    var val_array = value.split(' ');
    if(value.length==6) {
      value = '#' + value;
    } else if(value.length ==27 && val_array.length == 4) {
      var old_len = value.length;
      var new_vals = [];
      for(i=0;i<4;i++) new_vals[i] = '#' + val_array[i];
      value = new_vals.join(' ');
    }
  }
  if(css_selector.tab == 'List') {
   var selector = g_selector + ' UL, ' + g_selector + ' OL';
   var remote = $(window.opener).length == 1;
   $target = remote ? window.opener.$(selector) : $(selector);
  }
  
  if(altfield = css_selector.altfield) {
    $target.css(altfield, value); // update target css
    $('#' +altfield).val(value); // write to alt input
  } else {
    //alert("Setting " + css_selector.name + ' of ' + $target.attr('id') + " to " + value);
    $target.css(css_selector.name, value);
  }
  layout_changed();
}

function layout_css_read($target, css_selector) {
  //var remote = $(window.opener).length == 1;
  //var $target = remote ? window.opener.$(selector) : $(selector);
  var css_property = css_selector.altfield ? css_selector.altfield : css_selector.name;
  var val_array = new Array();
  var all_same = true;
  
  if(css_selector.directional) {
    for(var i = 0; i < g_dir_array.length; i++) {
      var dir = g_dir_array[i];    
      var dir_id = layout_directional_id(css_property, dir);
      var $dir_input = $('#' + dir_id);
      var css_dir_selector = $dir_input.data('css_selector');
      val_array[i] = layout_css_read($target, css_dir_selector); // $target.css(css_dir_property);
      //val_array[i] = $target.css(css_dir_property);
      if(i > 0 && val_array[i] != val_array[0]) all_same = false;
    }
    return all_same ? val_array[0] : val_array.join(' ');
    //alert(val_array.join(' '));
  }
    
  // below is a hack since jQuery doesn't recognize "border-width", only "border-top-width" 
  var parts = [];
  if(css_property.indexOf('border-') ==0) {
    parts = css_property.split('-');
    if(parts.length==2) css_property = parts[0] + '-top-' + parts[1];
  } else if(css_property == 'margin' || css_property == 'padding') {
    css_property = css_property + '-top';
  }
  
  var css_val = $target.css(css_property);
  if(css_selector.type == 'color') css_val = rgb2hex(css_val);
  else if(css_selector.type == 'slider' && isNaN(parseFloat(css_val))) css_val = ''; // don't allow non-numbers
  
  //   var old_val = css_val;
  //   css_val = rgb2hex(css_val);
  //   //if(css_property == 'border-top-color') alert("ov=" + old_val + " nv=" + css_val);
  //   // alert("name=" +  css_property + "ov=" + old_val + " nv=" + css_val);
  // }                                                                   
  return css_val;
}


function layout_select_box(css_selector) {
 var $input = $("#" + css_selector.name);
  $input.bind('change', function() {
    //layout_css_write($(this).data('target'), css_selector, this.value);
    layout_css_write($g_target, css_selector, this.value);
    if(css_selector.parent) layout_direction_join(css_selector);
  }); 
  
  $('#' + css_selector.name + ' option').hover(function() {
    //layout_css_write($(this).parent().data('target'), css_selector, this.value);
    layout_css_write($g_target, css_selector, this.value);
  }); 
                                                              
  if(altfield = css_selector.altfield) {
    var $altTarget = $('#' + altfield);
    $altTarget.bind('change', function() {
        //layout_css_write($('#' + css_selector.name).data('target'), css_selector, this.value);
        layout_css_write($g_target, css_selector, this.value);
        if(css_selector.parent) layout_direction_join(css_selector);
      }); 
  }
}

function layout_slider(css_selector) {
  var min = css_selector.min ? css_selector.min : 0;
  var max = css_selector.max ? css_selector.max : 1000; 
  var orientation = css_selector.orientation ? css_selector.orientation : 'horizontal'; 
  var step = css_selector.step ? css_selector.step : 1;
  var unit = css_selector.unit; // todo: use actual, default to selector unit
  // if(orientation == 'vertical') {
  //   var min0 = min;
  //   min = max;
  //   max = min0;
  //   step = -1;
  // }
  var $input = $("#" + css_selector.name);
  var $slider = $("#" + css_selector.name + '-slider');
  // $slider.slider("destroy");      
  
  // var css_val = $target.css(css_selector);
  // var css_intval = css_val ? parseInt(css_val) : 0;

  //if(css_selector == 'border-width') alert("target=" + target + " bw=" + css_val + " border=" + $target.css('border'));
  $slider.slider({
    min: min,     
    max: max,
    step: step,
//    orientation: orientation,
//    range: "min",      
//     value: 0, // set dynamically somewhere else
//      alert(css_selctor.name + " of val = " + ui.value);
//      var id = $target.attr('id');
//      alert(css_selctor.name + " of target id = " + id + ' val=' + ui.value);

  slide: function(event, ui) {
      //var $target = $input.data('target');
      if(!$g_target) return;
      layout_css_write($g_target, css_selector, ui.value)
      //$g_target.css(css_selector.name, ui.value);
      $input.val(ui.value + unit);
      layout_changed();
      if(css_selector.parent) layout_direction_join(css_selector);
      // if(css_selector == 'border-top-width') alert("Setting " + css_selector + " of " + $target.attr('id') + ' to ' + ui.value);
    }
//    change: layout_changed
  });
  $input.bind('change', function() {
    if(!$g_target) return;
    layout_changed();
    //var $target = $input.data('target');
    $slider.slider("value", parseInt(this.value));
    layout_css_write($g_target, css_selector, this.value)
    if(css_selector.parent) layout_direction_join(css_selector);
    //$g_target.css(css_selector.name, this.value);
  });

}


// turns a text input into a color picker
// if target is set, dynamically update color of target
function layout_color_picker(css_selector) {   
   var $input = $("#" + css_selector.name);
   $input.ColorPicker({
     onSubmit: function(hsb, hex, rgb, el) {
       $(el).val(hex);
       $(el).ColorPickerHide();
       var brightness = (rgb.r+ rgb.g + rgb.b) / 765;
       var fg = brightness < 0.5 ? '#FFFFFF' : '#000000';
       $(el).css('color', fg);
       $(el).css('background-color', '#' + hex);        
     },
     onBeforeShow: function () {
       $(this).ColorPickerSetColor(this.value);
     }, 
     onChange: function (hsb, hex, rgb, el) {                                
       // $(el).val(hex);
       // $(el).css('background-color', '#' + hex);
       if(!$g_target) return;
       set_color(css_selector.name, hex);
       //var $target = $input.data('target');
       $g_target.css(css_selector.name, '#' + hex);     
        if(css_selector.parent) layout_direction_join(css_selector);
       layout_changed();
     }  
   })
   .bind('change', function() {
     if(!$g_target) return;
     $(this).ColorPickerSetColor(this.value);
     set_color(css_selector.name, this.value);
     //var $target = $input.data('target');
     $g_target.css(css_selector.name, '#' + this.value);
     if(css_selector.parent) layout_direction_join(css_selector);
   });
  //set_color(css_selector, ) // handled by hover
}                                                

function layout_changed() {
  // if(g_css_changed) return;
  g_css_changed = true;
  // alert("layout changed");
  $("#page_id").attr('disabled', true);
  $("#div_select").attr('disabled', true);
  $("#css_save").attr('disabled', false);
  $("#css_cancel").attr('disabled', false);  
}

// store original values for reset and target input
function layout_save_original($target, css_selectors) {
  if(!css_selectors) var css_selectors = g_css_selectors;
  var remote = $(window.opener).length == 1;
  // var $target = remote ? window.opener.$(selector) : $(selector);
  // alert('saving original remote=' + remote + ' selector=' + selector + ' target=' + $target.attr('id') + ' num selectors=' + $(css_selectors).length);
  for( var i = 0; i < css_selectors.length; i++ ) {
    css_selector = css_selectors[i];
    var unit = css_selector.unit;
    var $input = $('#' + css_selector.name);
    var org_val = layout_css_read($target, css_selector);

    if(css_selector.name == 'width' && $target.attr('id') == 'footer') alert(css_selector.name + ' of ' + $target.attr('id') + ' = ' + org_val);
    
    $input.data('orgval', org_val);
    $input.data('target', $target);
    if(css_selector.directional) {
      var $dir_input = $('#' + css_selector.name + '-directional');
      $dir_input.data('orgval', $dir_input.attr('checked') ? true : false);
      //alert('org val of ' + '#' + css_selector.name + '-directional' + ' = ' + $dir_input.attr('checked'));
    }
  }
}

function layout_close() {
  if(g_css_changed && !confirm("You have unsaved changes to the layout. Are you sure you want to close the dialog (your changes will be lost) ?")) return false;  
  if(g_div_edited) {
    $(g_div_edited).resizable('destroy');
    $(g_div_edited).draggable('destroy');
  }
  
  var remote = $(window.opener).length == 1;
  var $target = remote ? window.opener.$("a") : $("a");
  $target.unbind('click'); 
  layout_reset();
  if(remote) window.close();
  return true;
}


// Dynatree functions 
function dynatree_addnode(rootNode, data) {        
  var childNode = rootNode.addChild({
    key: data.id,
    title: data.name,
    isFolder: data.is_folder == 1
  });
  return childNode;
}

function dynatree_removenode(rootNode, title, is_folder) {        
}

function dynatree_totrash(sourceNode) {
  var $trash = $('#trash_tree');               
  var node = $trash.dynatree("getRoot");
  var hitMode = 'over';
  var target_id = '0';
  var ajax_url = "/admin/app_data.php?oper=tree_update&obj_type=site_page&ac=tree_update&id=" + sourceNode.data.key + "&target=" + node.data.key + "&mode=" + hitMode + "&trash=1";
  //var ajax_url = "/admin/app_data.php?oper=tree_update&obj_type=site_page&ac=tree_update&id=" + sourceNode.data.key + "&target=" + target_id + "&mode=" + hitMode + "&trash=1";
  // alert(ajax_url);
  //return;
  jQuery.ajax({
    type: "get",
      url: ajax_url,
      success: function (responseText) {
        // alert(responseText);
        logMsg("tree.onDrop(%o, %o, %s)", node, sourceNode, hitMode);
        sourceNode.move(node, hitMode);
        dynatree_update_trash();
    }
  });

}

function dynatree_empty_trash(node) {
  if(!confirm('Are you sure you want to permanently delete the images in the trash?')) return false;
  var ids = new Array();
  var $trash = $('#trash_tree');               
  var node = $trash.dynatree("getRoot");
  var cb = node.toDict(true, function(dict){
      ids.push(dict.key);
  });

  var ids_str = ids.toString();
  $.ajax({ 
    url: "/admin/app_data.php?obj_type=site_page", 
    type: "POST", 
    data: "obj_type=site_page&oper=del&id="+ ids_str,
    success: function(responseText) {
      var $trash = $('#trash_tree');               
      var node = $trash.dynatree("getRoot");
      node.removeChildren();
      dynatree_update_trash();
    }    
  });
  return false;
}

// adds empty icon, hides "empty trash link"
// or removes empty icon, shows "empty trash link" as needed

function dynatree_update_trash() {
  $trash = $('#trash_tree');
  var trash_tree = $trash.dynatree("getTree");
  var trash_root = $trash.dynatree("getRoot");
  var count = trash_tree? trash_tree.count() : 0;
  if(!count || count==1) {
    var node_data = [];
    node_data.name = '[empty]';
    node_data.is_folder = true;
    node_data.id = '__trash';
    dynatree_addnode(trash_root, node_data)
    $('#tree_empty_trash').hide();
  } else if(count >= 2) {
    var empty_node = $trash.dynatree("getTree").getNodeByKey("__trash");
    if(empty_node) empty_node.remove();
    $('#tree_empty_trash').show();
  }  
  return;  
}

// called from cms site when page is successfully saved
function cms_save(data) {
  //alert(dump(data));
  window.location = '/?goto_page&page_id=' + data.id;
}


function dynatree_save(data) {
  //alert(data_json);
  //var data = jQuery.parseJSON(data_json);
  var id = data.id;
  var parent_id = data.parent_id;
  
  var $tree = $('#pages_tree');
  var active = $tree.dynatree("getActiveNode");
  var rootNode = active && active.data.title != 'Home' ? active : $tree.dynatree("getRoot");
  if(id) { // update
    var node = $tree.dynatree("getTree").selectKey(id);
    if(node) { 
      node.data.title = data.name;
      node.data.isFolder = data.is_folder == 1;
      node.render();
    } else {
      var childNode = dynatree_addnode(rootNode, data);      
    }
  } else { // add
    alert("dynatree_save: no id, shouldn't get here");
    var childNode = dynatree_addnode(rootNode, data);
  }

  if(parent_id) { // expand parent
    var parent_node = $tree.dynatree("getTree").selectKey(parent_id);
    parent_node.expand();
  }
  //alert('hello' + dump(data) + " title=" + data.name);
}

function dynatree_init(site_id, id, trash) {
  var $tree = $('#' +id);
  $tree.dynatree({
  onClick: function(node, event) {
      var active = $tree.dynatree("getActiveNode");
      var tree = $tree.dynatree("getTree");
      if(active && active.data.key == node.data.key) { // deactivate active key if clicked again
        $tree.dynatree("activeKey");
        tree.activateKey("");
        tree.deactivateKey(0);
      }
      //alert("click on " + node.data.key + " active=" + (active ? active.data.key : ""));        
      //if( node.getEventTargetType(event) == "title" ) node.toggleSelect();
    },

  onDblClick: function(node, event) {
      if(node.data.title == '[empty]') return false;
      var tree = $tree.dynatree("getTree");
      var title = node.data.title;
      var page_fields = ['site_id', 'parent_id', 'name', 'show_menu', 'show_footer', 'localized', 'is_folder'];
      var data = [];
      object_dialog('site_page', node.data.key, page_fields, data, 'dynatree_save');                                      
      //edit_page_dialog(site_id, node.data.key, false, 'dynatree_save');

    },
    
    onKeydown: function(node, event) {
      // alert(event.which);
      if( event.which == 46 ) { // delete        
        if(node.data.title == '[empty]' || node.data.title == 'Home') return false;
        dynatree_totrash(node);
        return false;
      }
    },

    dnd: {
      onDragStart: function(node) {
        if(node.data.title == '[empty]' || node.data.title == 'Home') return false;
        /** This function MUST be defined to enable dragging for the tree.
         *  Return false to cancel dragging of node.
         */
        logMsg("tree.onDragStart(%o)", node);
        return true;
      },
      onDragStop: function(node) {
        // This function is optional.
        logMsg("tree.onDragStop(%o)", node);
      },
      autoExpandMS: 1000,
      preventVoidMoves: true, // Prevent dropping nodes \'before self\', etc.
      onDragEnter: function(node, sourceNode) {
        /** sourceNode may be null for non-dynatree droppables.
         *  Return false to disallow dropping on node. In this case
         *  onDragOver and onDragLeave are not called.
         *  Return \'over\', \'before, or \'after\' to force a hitMode.
         *  Return [\'before\', \'after\'] to restrict available hitModes.
         *  Any other return value will calc the hitMode from the cursor position.
         */
        logMsg("tree.onDragEnter(%o, %o)", node, sourceNode);
        // Prevent dropping a parent below it\'s own child
//                if(node.isDescendantOf(sourceNode))
//                    return false;
        // Prevent dropping a parent below another parent (only sort
        // nodes under the same parent)
//                if(node.parent !== sourceNode.parent)
//                    return false;
//              if(node === sourceNode)
//                  return false;
        // Don\'t allow dropping *over* a node (would create a child)
//        return ["before", "after"];
        return true;
      },
      onDragOver: function(node, sourceNode, hitMode) {
        /** Return false to disallow dropping this node.
         *
         */
        logMsg("tree.onDragOver(%o, %o, %o)", node, sourceNode, hitMode);
        // Prohibit creating childs in non-folders (only sorting allowed)
//        if( !node.isFolder && hitMode == "over" )
//          return "after";
      },
      onDrop: function(node, sourceNode, hitMode, ui, draggable) {
        /** This function MUST be defined to enable dropping of items on
         * the tree.
         */
        
        //alert("tree.onDrop(%o, %o, %s)" + "node=" + node.data.title + " source= " + sourceNode.data.key + " hitMode=" + hitMode + " type=" + typeof(node));
        if(node.data.title == '[empty]' || node.data.title == 'Home') hitMode = 'after';
        ajax_url = "/admin/app_data.php?oper=tree_update&obj_type=site_page&ac=tree_update&id=" + sourceNode.data.key + "&target=" + node.data.key + "&mode=" + hitMode + "&trash=" + trash;
        jQuery.ajax({
          type: "get",
          url: ajax_url,
          success: function (responseText) {
            logMsg("tree.onDrop(%o, %o, %s)", node, sourceNode, hitMode);
            sourceNode.move(node, hitMode);
            dynatree_update_trash();
          }
        });
        
        if(sourceNode) {
          logMsg("tree.onDrop(%o, %o, %s)", node, sourceNode, hitMode);
          sourceNode.move(node, hitMode);
        } else {
          alert("no sn");
        }
        // expand the drop target
//        sourceNode.expand(true);
      },
      onDragLeave: function(node, sourceNode) {
        /** Always called if onDragEnter was called.
         */
        logMsg("tree.onDragLeave(%o, %o)", node, sourceNode);
      }
    }
  });

  if(trash) return;

  // bind handlers to buttons Add Page/Add Folder
  $(".add_node").click(function() {
    var $tree = $('#' +id);
    var active = $tree.dynatree("getActiveNode");

    var is_folder = $(this).attr("id") == "add_folder" ? 1 : 0;
    var parent_id = active ? active.data.key : 0;

    var page_fields = ['site_id', 'parent_id', 'name', 'show_menu', 'show_footer', 'localized', 'is_folder'];
    var data = {"site_id": site_id, "is_folder": is_folder, "parent_id": parent_id};
    //alert(dump(data));
    object_dialog('site_page', 0, page_fields, data, 'dynatree_save');
    //add_page_dialog(site_id, parent_id, is_folder, 'dynatree_save');

    return false;

    //var title = $("#page_name").val();
    //if(!title) {alert("Please fill in a name");return false;}
    //var page_type = $("#page_type").val();
    //
    //var rootNode = active ? active : $tree.dynatree("getRoot");
    //var ajax_url = "/admin/app_data.php?oper=add&obj_type=site_page&oper=add";
    //alert(ajax_url);
    //jQuery.ajax({
    //  type: "POST",
    //  data: "obj_type=media&oper=edit&site_id=" + site_id + "&parent_id="+ parent_id + "&name=" + title + "&is_folder=" + is_folder + "&page_type=" + page_type,
    //  url: ajax_url,
    //  success: function (responseText) {
    //    //var result = jQuery.parseJSON(responseText);
    //    var childNode = dynatree_addnode(rootNode, title, is_folder);
    //    $("#page_name").val("");
    //
    //    if(active) active.expand(true);
    //    alert('success:' + responseText);
    //  },
    //  error: function(request, error) {
    //    alert("Error: " + error)     
    //  }
    //});
    return false;
  });

}
// End Dynatree functions 


/* end CMS */

/*
 * debug
 * Simply loops thru each jquery item and logs it
 */
jQuery.fn.debug = function() {
	return this.each(function(){
		$.log(this);
	});
};

/*
 * log
 * Send it anything, and it will add a line to the logging console.
 * If firebug is installed, it simple send the item to firebug.
 * If not, it creates a string representation of the html element (if message is an object), or just uses the supplied value (if not an object).
 */
jQuery.log = function(message){
	// only if debugging is on
	if( window.DEBUG ){
		// if no firebug, build a debug line from the actual html element if it's an object, or just send the string
		var str = message;
		if( !('firebug' in console) ){
			if( typeof(message) == 'object' ){
				str = '&lt;';
				str += message.nodeName.toLowerCase();
				for( var i = 0; i < message.attributes.length; i++ ){
					str += ' ' + message.attributes[i].nodeName.toLowerCase() + '="' + message.attributes[i].nodeValue + '"';
				}
				str += '&gt;';
			}
		}
		console.debug(str);
	}
};

// end logging

// curvyCorners: http://www.curvycorners.net/
//var curvyCornersVerbose = false;
//function browserdetect(){var A=navigator.userAgent.toLowerCase();this.isIE=A.indexOf("msie")>-1;this.ieVer=this.isIE?/msie\s(\d\.\d)/.exec(A)[1]:0;this.isMoz=A.indexOf("firefox")!=-1;this.isSafari=A.indexOf("safari")!=-1;this.quirksMode=this.isIE&&(!document.compatMode||document.compatMode.indexOf("BackCompat")>-1);this.isOp="opera" in window;this.isWebKit=A.indexOf("webkit")!=-1;if(this.isIE){this.get_style=function(D,F){if(!(F in D.currentStyle)){return""}var C=/^([\d.]+)(\w*)/.exec(D.currentStyle[F]);if(!C){return D.currentStyle[F]}if(C[1]==0){return"0"}if(C[2]&&C[2]!=="px"){var B=D.style.left;var E=D.runtimeStyle.left;D.runtimeStyle.left=D.currentStyle.left;D.style.left=C[1]+C[2];C[0]=D.style.pixelLeft;D.style.left=B;D.runtimeStyle.left=E}return C[0]}}else{this.get_style=function(B,C){C=C.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();return document.defaultView.getComputedStyle(B,"").getPropertyValue(C)}}}var curvyBrowser=new browserdetect;if(curvyBrowser.isIE){try{document.execCommand("BackgroundImageCache",false,true)}catch(e){}}function curvyCnrSpec(A){this.selectorText=A;this.tlR=this.trR=this.blR=this.brR=0;this.tlu=this.tru=this.blu=this.bru="";this.antiAlias=true}curvyCnrSpec.prototype.setcorner=function(B,C,A,D){if(!B){this.tlR=this.trR=this.blR=this.brR=parseInt(A);this.tlu=this.tru=this.blu=this.bru=D}else{propname=B.charAt(0)+C.charAt(0);this[propname+"R"]=parseInt(A);this[propname+"u"]=D}};curvyCnrSpec.prototype.get=function(D){if(/^(t|b)(l|r)(R|u)$/.test(D)){return this[D]}if(/^(t|b)(l|r)Ru$/.test(D)){var C=D.charAt(0)+D.charAt(1);return this[C+"R"]+this[C+"u"]}if(/^(t|b)Ru?$/.test(D)){var B=D.charAt(0);B+=this[B+"lR"]>this[B+"rR"]?"l":"r";var A=this[B+"R"];if(D.length===3&&D.charAt(2)==="u"){A+=this[B="u"]}return A}throw new Error("Don't recognize property "+D)};curvyCnrSpec.prototype.radiusdiff=function(A){if(A!=="t"&&A!=="b"){throw new Error("Param must be 't' or 'b'")}return Math.abs(this[A+"lR"]-this[A+"rR"])};curvyCnrSpec.prototype.setfrom=function(A){this.tlu=this.tru=this.blu=this.bru="px";if("tl" in A){this.tlR=A.tl.radius}if("tr" in A){this.trR=A.tr.radius}if("bl" in A){this.blR=A.bl.radius}if("br" in A){this.brR=A.br.radius}if("antiAlias" in A){this.antiAlias=A.antiAlias}};curvyCnrSpec.prototype.cloneOn=function(G){var E=["tl","tr","bl","br"];var H=0;var C,A;for(C in E){if(!isNaN(C)){A=this[E[C]+"u"];if(A!==""&&A!=="px"){H=new curvyCnrSpec;break}}}if(!H){H=this}else{var B,D,F=curvyBrowser.get_style(G,"left");for(C in E){if(!isNaN(C)){B=E[C];A=this[B+"u"];D=this[B+"R"];if(A!=="px"){var F=G.style.left;G.style.left=D+A;D=G.style.pixelLeft;G.style.left=F}H[B+"R"]=D;H[B+"u"]="px"}}G.style.left=F}return H};curvyCnrSpec.prototype.radiusSum=function(A){if(A!=="t"&&A!=="b"){throw new Error("Param must be 't' or 'b'")}return this[A+"lR"]+this[A+"rR"]};curvyCnrSpec.prototype.radiusCount=function(A){var B=0;if(this[A+"lR"]){++B}if(this[A+"rR"]){++B}return B};curvyCnrSpec.prototype.cornerNames=function(){var A=[];if(this.tlR){A.push("tl")}if(this.trR){A.push("tr")}if(this.blR){A.push("bl")}if(this.brR){A.push("br")}return A};function operasheet(C){var A=document.styleSheets.item(C).ownerNode.text;A=A.replace(/\/\*(\n|\r|.)*?\*\//g,"");var D=new RegExp("^s*([\\w.#][-\\w.#, ]+)[\\n\\s]*\\{([^}]+border-((top|bottom)-(left|right)-)?radius[^}]*)\\}","mg");var G;this.rules=[];while((G=D.exec(A))!==null){var F=new RegExp("(..)border-((top|bottom)-(left|right)-)?radius:\\s*([\\d.]+)(in|em|px|ex|pt)","g");var E,B=new curvyCnrSpec(G[1]);while((E=F.exec(G[2]))!==null){if(E[1]!=="z-"){B.setcorner(E[3],E[4],E[5],E[6])}}this.rules.push(B)}}operasheet.contains_border_radius=function(A){return/border-((top|bottom)-(left|right)-)?radius/.test(document.styleSheets.item(A).ownerNode.text)};function curvyCorners(){var G,D,E,B,J;if(typeof arguments[0]!=="object"){throw curvyCorners.newError("First parameter of curvyCorners() must be an object.")}if(arguments[0] instanceof curvyCnrSpec){B=arguments[0];if(!B.selectorText&&typeof arguments[1]==="string"){B.selectorText=arguments[1]}}else{if(typeof arguments[1]!=="object"&&typeof arguments[1]!=="string"){throw curvyCorners.newError("Second parameter of curvyCorners() must be an object or a class name.")}D=arguments[1];if(typeof D!=="string"){D=""}if(D!==""&&D.charAt(0)!=="."&&"autoPad" in arguments[0]){D="."+D}B=new curvyCnrSpec(D);B.setfrom(arguments[0])}if(B.selectorText){J=0;var I=B.selectorText.replace(/\s+$/,"").split(/,\s*/);E=new Array;function A(M){var L=M.split("#");return(L.length===2?"#":"")+L.pop()}for(G=0;G<I.length;++G){var K=A(I[G]);var H=K.split(" ");switch(K.charAt(0)){case"#":D=H.length===1?K:H[0];D=document.getElementById(D.substr(1));if(D===null){curvyCorners.alert("No object with ID "+K+" exists yet.\nCall curvyCorners(settings, obj) when it is created.")}else{if(H.length===1){E.push(D)}else{E=E.concat(curvyCorners.getElementsByClass(H[1],D))}}break;default:if(H.length===1){E=E.concat(curvyCorners.getElementsByClass(K))}else{var C=curvyCorners.getElementsByClass(H[0]);for(D=0;D<C.length;++D){E=E.concat(curvyCorners.getElementsByClass(H[1],C))}}}}}else{J=1;E=arguments}for(G=J,D=E.length;G<D;++G){if(E[G]&&(!("IEborderRadius" in E[G].style)||E[G].style.IEborderRadius!="set")){if(E[G].className&&E[G].className.indexOf("curvyRedraw")!==-1){if(typeof curvyCorners.redrawList==="undefined"){curvyCorners.redrawList=new Array}curvyCorners.redrawList.push({node:E[G],spec:B,copy:E[G].cloneNode(false)})}E[G].style.IEborderRadius="set";var F=new curvyObject(B,E[G]);F.applyCorners()}}}curvyCorners.prototype.applyCornersToAll=function(){curvyCorners.alert("This function is now redundant. Just call curvyCorners(). See documentation.")};curvyCorners.redraw=function(){if(!curvyBrowser.isOp&&!curvyBrowser.isIE){return}if(!curvyCorners.redrawList){throw curvyCorners.newError("curvyCorners.redraw() has nothing to redraw.")}var E=curvyCorners.bock_redraw;curvyCorners.block_redraw=true;for(var A in curvyCorners.redrawList){if(isNaN(A)){continue}var D=curvyCorners.redrawList[A];if(!D.node.clientWidth){continue}var B=D.copy.cloneNode(false);for(var C=D.node.firstChild;C!=null;C=C.nextSibling){if(C.className==="autoPadDiv"){break}}if(!C){curvyCorners.alert("Couldn't find autoPad DIV");break}D.node.parentNode.replaceChild(B,D.node);while(C.firstChild){B.appendChild(C.removeChild(C.firstChild))}D=new curvyObject(D.spec,D.node=B);D.applyCorners()}curvyCorners.block_redraw=E};curvyCorners.adjust=function(obj,prop,newval){if(curvyBrowser.isOp||curvyBrowser.isIE){if(!curvyCorners.redrawList){throw curvyCorners.newError("curvyCorners.adjust() has nothing to adjust.")}var i,j=curvyCorners.redrawList.length;for(i=0;i<j;++i){if(curvyCorners.redrawList[i].node===obj){break}}if(i===j){throw curvyCorners.newError("Object not redrawable")}obj=curvyCorners.redrawList[i].copy}if(prop.indexOf(".")===-1){obj[prop]=newval}else{eval("obj."+prop+"='"+newval+"'")}};curvyCorners.handleWinResize=function(){if(!curvyCorners.block_redraw){curvyCorners.redraw()}};curvyCorners.setWinResize=function(A){curvyCorners.block_redraw=!A};curvyCorners.newError=function(A){return new Error("curvyCorners Error:\n"+A)};curvyCorners.alert=function(A){if(typeof curvyCornersVerbose==="undefined"||curvyCornersVerbose){alert(A)}};function curvyObject(){var U;this.box=arguments[1];this.settings=arguments[0];this.topContainer=this.bottomContainer=this.shell=U=null;var K=this.box.clientWidth;if(!K&&curvyBrowser.isIE){this.box.style.zoom=1;K=this.box.clientWidth}if(!K){if(!this.box.parentNode){throw this.newError("box has no parent!")}for(U=this.box;;U=U.parentNode){if(!U||U.tagName==="BODY"){this.applyCorners=function(){};curvyCorners.alert(this.errmsg("zero-width box with no accountable parent","warning"));return}if(U.style.display==="none"){break}}U.style.display="block";K=this.box.clientWidth}if(arguments[0] instanceof curvyCnrSpec){this.spec=arguments[0].cloneOn(this.box)}else{this.spec=new curvyCnrSpec("");this.spec.setfrom(this.settings)}var b=curvyBrowser.get_style(this.box,"borderTopWidth");var J=curvyBrowser.get_style(this.box,"borderBottomWidth");var D=curvyBrowser.get_style(this.box,"borderLeftWidth");var B=curvyBrowser.get_style(this.box,"borderRightWidth");var I=curvyBrowser.get_style(this.box,"borderTopColor");var G=curvyBrowser.get_style(this.box,"borderBottomColor");var A=curvyBrowser.get_style(this.box,"borderLeftColor");var E=curvyBrowser.get_style(this.box,"backgroundColor");var C=curvyBrowser.get_style(this.box,"backgroundImage");var Y=curvyBrowser.get_style(this.box,"backgroundRepeat");if(this.box.currentStyle&&this.box.currentStyle.backgroundPositionX){var R=curvyBrowser.get_style(this.box,"backgroundPositionX");var P=curvyBrowser.get_style(this.box,"backgroundPositionY")}else{var R=curvyBrowser.get_style(this.box,"backgroundPosition");R=R.split(" ");var P=R[1];R=R[0]}var O=curvyBrowser.get_style(this.box,"position");var Z=curvyBrowser.get_style(this.box,"paddingTop");var c=curvyBrowser.get_style(this.box,"paddingBottom");var Q=curvyBrowser.get_style(this.box,"paddingLeft");var a=curvyBrowser.get_style(this.box,"paddingRight");var S=curvyBrowser.get_style(this.box,"border");filter=curvyBrowser.ieVer>7?curvyBrowser.get_style(this.box,"filter"):null;var H=this.spec.get("tR");var M=this.spec.get("bR");var W=function(f){if(typeof f==="number"){return f}if(typeof f!=="string"){throw new Error("unexpected styleToNPx type "+typeof f)}var d=/^[-\d.]([a-z]+)$/.exec(f);if(d&&d[1]!="px"){throw new Error("Unexpected unit "+d[1])}if(isNaN(f=parseInt(f))){f=0}return f};var T=function(d){return d<=0?"0":d+"px"};try{this.borderWidth=W(b);this.borderWidthB=W(J);this.borderWidthL=W(D);this.borderWidthR=W(B);this.boxColour=curvyObject.format_colour(E);this.topPadding=W(Z);this.bottomPadding=W(c);this.leftPadding=W(Q);this.rightPadding=W(a);this.boxWidth=K;this.boxHeight=this.box.clientHeight;this.borderColour=curvyObject.format_colour(I);this.borderColourB=curvyObject.format_colour(G);this.borderColourL=curvyObject.format_colour(A);this.borderString=this.borderWidth+"px solid "+this.borderColour;this.borderStringB=this.borderWidthB+"px solid "+this.borderColourB;this.backgroundImage=((C!="none")?C:"");this.backgroundRepeat=Y}catch(X){throw this.newError("getMessage" in X?X.getMessage():X.message)}var F=this.boxHeight;var V=K;if(curvyBrowser.isOp){R=W(R);P=W(P);if(R){var N=V+this.borderWidthL+this.borderWidthR;if(R>N){R=N}R=(N/R*100)+"%"}if(P){var N=F+this.borderWidth+this.borderWidthB;if(P>N){P=N}P=(N/P*100)+"%"}}if(curvyBrowser.quirksMode){}else{this.boxWidth-=this.leftPadding+this.rightPadding;this.boxHeight-=this.topPadding+this.bottomPadding}this.contentContainer=document.createElement("div");if(filter){this.contentContainer.style.filter=filter}while(this.box.firstChild){this.contentContainer.appendChild(this.box.removeChild(this.box.firstChild))}if(O!="absolute"){this.box.style.position="relative"}this.box.style.padding="0";this.box.style.border=this.box.style.backgroundImage="none";this.box.style.backgroundColor="transparent";this.box.style.width=(V+this.borderWidthL+this.borderWidthR)+"px";this.box.style.height=(F+this.borderWidth+this.borderWidthB)+"px";var L=document.createElement("div");L.style.position="absolute";if(filter){L.style.filter=filter}if(curvyBrowser.quirksMode){L.style.width=(V+this.borderWidthL+this.borderWidthR)+"px"}else{L.style.width=V+"px"}L.style.height=T(F+this.borderWidth+this.borderWidthB-H-M);L.style.padding="0";L.style.top=H+"px";L.style.left="0";if(this.borderWidthL){L.style.borderLeft=this.borderWidthL+"px solid "+this.borderColourL}if(this.borderWidth&&!H){L.style.borderTop=this.borderWidth+"px solid "+this.borderColour}if(this.borderWidthR){L.style.borderRight=this.borderWidthR+"px solid "+this.borderColourL}if(this.borderWidthB&&!M){L.style.borderBottom=this.borderWidthB+"px solid "+this.borderColourB}L.style.backgroundColor=E;L.style.backgroundImage=this.backgroundImage;L.style.backgroundRepeat=this.backgroundRepeat;this.shell=this.box.appendChild(L);K=curvyBrowser.get_style(this.shell,"width");if(K===""||K==="auto"||K.indexOf("%")!==-1){throw this.newError("Shell width is "+K)}this.boxWidth=(K!=""&&K!="auto"&&K.indexOf("%")==-1)?parseInt(K):this.shell.clientWidth;this.applyCorners=function(){if(this.backgroundObject){var w=function(AO,i,t){if(AO===0){return 0}var k;if(AO==="right"||AO==="bottom"){return t-i}if(AO==="center"){return(t-i)/2}if(AO.indexOf("%")>0){return(t-i)*100/parseInt(AO)}return W(AO)};this.backgroundPosX=w(R,this.backgroundObject.width,V);this.backgroundPosY=w(P,this.backgroundObject.height,F)}else{if(this.backgroundImage){this.backgroundPosX=W(R);this.backgroundPosY=W(P)}}if(H){v=document.createElement("div");v.style.width=this.boxWidth+"px";v.style.fontSize="1px";v.style.overflow="hidden";v.style.position="absolute";v.style.paddingLeft=this.borderWidth+"px";v.style.paddingRight=this.borderWidth+"px";v.style.height=H+"px";v.style.top=-H+"px";v.style.left=-this.borderWidthL+"px";this.topContainer=this.shell.appendChild(v)}if(M){var v=document.createElement("div");v.style.width=this.boxWidth+"px";v.style.fontSize="1px";v.style.overflow="hidden";v.style.position="absolute";v.style.paddingLeft=this.borderWidthB+"px";v.style.paddingRight=this.borderWidthB+"px";v.style.height=M+"px";v.style.bottom=-M+"px";v.style.left=-this.borderWidthL+"px";this.bottomContainer=this.shell.appendChild(v)}var AG=this.spec.cornerNames();for(var AK in AG){if(!isNaN(AK)){var AC=AG[AK];var AD=this.spec[AC+"R"];var AE,AH,j,AF;if(AC=="tr"||AC=="tl"){AE=this.borderWidth;AH=this.borderColour;AF=this.borderWidth}else{AE=this.borderWidthB;AH=this.borderColourB;AF=this.borderWidthB}j=AD-AF;var u=document.createElement("div");u.style.height=this.spec.get(AC+"Ru");u.style.width=this.spec.get(AC+"Ru");u.style.position="absolute";u.style.fontSize="1px";u.style.overflow="hidden";var r,q,p;var n=filter?parseInt(/alpha\(opacity.(\d+)\)/.exec(filter)[1]):100;for(r=0;r<AD;++r){var m=(r+1>=j)?-1:Math.floor(Math.sqrt(Math.pow(j,2)-Math.pow(r+1,2)))-1;if(j!=AD){var h=(r>=j)?-1:Math.ceil(Math.sqrt(Math.pow(j,2)-Math.pow(r,2)));var f=(r+1>=AD)?-1:Math.floor(Math.sqrt(Math.pow(AD,2)-Math.pow((r+1),2)))-1}var d=(r>=AD)?-1:Math.ceil(Math.sqrt(Math.pow(AD,2)-Math.pow(r,2)));if(m>-1){this.drawPixel(r,0,this.boxColour,n,(m+1),u,true,AD)}if(j!=AD){if(this.spec.antiAlias){for(q=m+1;q<h;++q){if(this.backgroundImage!=""){var g=curvyObject.pixelFraction(r,q,j)*100;this.drawPixel(r,q,AH,n,1,u,g>=30,AD)}else{if(this.boxColour!=="transparent"){var AB=curvyObject.BlendColour(this.boxColour,AH,curvyObject.pixelFraction(r,q,j));this.drawPixel(r,q,AB,n,1,u,false,AD)}else{this.drawPixel(r,q,AH,n>>1,1,u,false,AD)}}}if(f>=h){if(h==-1){h=0}this.drawPixel(r,h,AH,n,(f-h+1),u,false,0)}p=AH;q=f}else{if(f>m){this.drawPixel(r,(m+1),AH,n,(f-m),u,false,0)}}}else{p=this.boxColour;q=m}if(this.spec.antiAlias){while(++q<d){this.drawPixel(r,q,p,(curvyObject.pixelFraction(r,q,AD)*n),1,u,AF<=0,AD)}}}for(var y=0,AJ=u.childNodes.length;y<AJ;++y){var s=u.childNodes[y];var AI=parseInt(s.style.top);var AM=parseInt(s.style.left);var AN=parseInt(s.style.height);if(AC=="tl"||AC=="bl"){s.style.left=(AD-AM-1)+"px"}if(AC=="tr"||AC=="tl"){s.style.top=(AD-AN-AI)+"px"}s.style.backgroundRepeat=this.backgroundRepeat;if(this.backgroundImage){switch(AC){case"tr":s.style.backgroundPosition=(this.backgroundPosX-this.borderWidthL+AD-V-AM)+"px "+(this.backgroundPosY+AN+AI+this.borderWidth-AD)+"px";break;case"tl":s.style.backgroundPosition=(this.backgroundPosX-AD+AM+this.borderWidthL)+"px "+(this.backgroundPosY-AD+AN+AI+this.borderWidth)+"px";break;case"bl":s.style.backgroundPosition=(this.backgroundPosX-AD+AM+1+this.borderWidthL)+"px "+(this.backgroundPosY-F-this.borderWidth+(curvyBrowser.quirksMode?AI:-AI)+AD)+"px";break;case"br":if(curvyBrowser.quirksMode){s.style.backgroundPosition=(this.backgroundPosX+this.borderWidthL-V+AD-AM)+"px "+(this.backgroundPosY-F-this.borderWidth+AI+AD)+"px"}else{s.style.backgroundPosition=(this.backgroundPosX-this.borderWidthL-V+AD-AM)+"px "+(this.backgroundPosY-F-this.borderWidth+AD-AI)+"px"}}}}switch(AC){case"tl":u.style.top=u.style.left="0";this.topContainer.appendChild(u);break;case"tr":u.style.top=u.style.right="0";this.topContainer.appendChild(u);break;case"bl":u.style.bottom=u.style.left="0";this.bottomContainer.appendChild(u);break;case"br":u.style.bottom=u.style.right="0";this.bottomContainer.appendChild(u)}}}var x={t:this.spec.radiusdiff("t"),b:this.spec.radiusdiff("b")};for(z in x){if(typeof z==="function"){continue}if(!this.spec.get(z+"R")){continue}if(x[z]){if(this.backgroundImage&&this.spec.radiusSum(z)!==x[z]){curvyCorners.alert(this.errmsg("Not supported: unequal non-zero top/bottom radii with background image"))}var AL=(this.spec[z+"lR"]<this.spec[z+"rR"])?z+"l":z+"r";var l=document.createElement("div");l.style.height=x[z]+"px";l.style.width=this.spec.get(AL+"Ru");l.style.position="absolute";l.style.fontSize="1px";l.style.overflow="hidden";l.style.backgroundColor=this.boxColour;switch(AL){case"tl":l.style.bottom=l.style.left="0";l.style.borderLeft=this.borderString;this.topContainer.appendChild(l);break;case"tr":l.style.bottom=l.style.right="0";l.style.borderRight=this.borderString;this.topContainer.appendChild(l);break;case"bl":l.style.top=l.style.left="0";l.style.borderLeft=this.borderStringB;this.bottomContainer.appendChild(l);break;case"br":l.style.top=l.style.right="0";l.style.borderRight=this.borderStringB;this.bottomContainer.appendChild(l)}}var o=document.createElement("div");if(filter){o.style.filter=filter}o.style.position="relative";o.style.fontSize="1px";o.style.overflow="hidden";o.style.width=this.fillerWidth(z);o.style.backgroundColor=this.boxColour;o.style.backgroundImage=this.backgroundImage;o.style.backgroundRepeat=this.backgroundRepeat;switch(z){case"t":if(this.topContainer){if(curvyBrowser.quirksMode){o.style.height=100+H+"px"}else{o.style.height=100+H-this.borderWidth+"px"}o.style.marginLeft=this.spec.tlR?(this.spec.tlR-this.borderWidthL)+"px":"0";o.style.borderTop=this.borderString;if(this.backgroundImage){var AA=this.spec.tlR?(this.backgroundPosX-(H-this.borderWidthL))+"px ":"0 ";o.style.backgroundPosition=AA+this.backgroundPosY+"px";this.shell.style.backgroundPosition=this.backgroundPosX+"px "+(this.backgroundPosY-H+this.borderWidthL)+"px"}this.topContainer.appendChild(o)}break;case"b":if(this.bottomContainer){if(curvyBrowser.quirksMode){o.style.height=M+"px"}else{o.style.height=M-this.borderWidthB+"px"}o.style.marginLeft=this.spec.blR?(this.spec.blR-this.borderWidthL)+"px":"0";o.style.borderBottom=this.borderStringB;if(this.backgroundImage){var AA=this.spec.blR?(this.backgroundPosX+this.borderWidthL-M)+"px ":this.backgroundPosX+"px ";o.style.backgroundPosition=AA+(this.backgroundPosY-F-this.borderWidth+M)+"px"}this.bottomContainer.appendChild(o)}}}this.contentContainer.style.position="absolute";this.contentContainer.className="autoPadDiv";this.contentContainer.style.left=this.borderWidthL+"px";this.contentContainer.style.paddingTop=this.topPadding+"px";this.contentContainer.style.top=this.borderWidth+"px";this.contentContainer.style.paddingLeft=this.leftPadding+"px";this.contentContainer.style.paddingRight=this.rightPadding+"px";z=V;if(!curvyBrowser.quirksMode){z-=this.leftPadding+this.rightPadding}this.contentContainer.style.width=z+"px";this.contentContainer.style.textAlign=curvyBrowser.get_style(this.box,"textAlign");this.box.style.textAlign="left";this.box.appendChild(this.contentContainer);if(U){U.style.display="none"}};if(this.backgroundImage){R=this.backgroundCheck(R);P=this.backgroundCheck(P);if(this.backgroundObject){this.backgroundObject.holdingElement=this;this.dispatch=this.applyCorners;this.applyCorners=function(){if(this.backgroundObject.complete){this.dispatch()}else{this.backgroundObject.onload=new Function("curvyObject.dispatch(this.holdingElement);")}}}}}curvyObject.prototype.backgroundCheck=function(B){if(B==="top"||B==="left"||parseInt(B)===0){return 0}if(!(/^[-\d.]+px$/.test(B))&&!this.backgroundObject){this.backgroundObject=new Image;var A=function(D){var C=/url\("?([^'"]+)"?\)/.exec(D);return(C?C[1]:D)};this.backgroundObject.src=A(this.backgroundImage)}return B};curvyObject.dispatch=function(A){if("dispatch" in A){A.dispatch()}else{throw A.newError("No dispatch function")}};curvyObject.prototype.drawPixel=function(J,G,A,F,H,I,C,E){var B=document.createElement("div");B.style.height=H+"px";B.style.width="1px";B.style.position="absolute";B.style.fontSize="1px";B.style.overflow="hidden";var D=this.spec.get("tR");B.style.backgroundColor=A;if(C&&this.backgroundImage!=""){B.style.backgroundImage=this.backgroundImage;B.style.backgroundPosition="-"+(this.boxWidth-(E-J)+this.borderWidth)+"px -"+((this.boxHeight+D+G)-this.borderWidth)+"px"}if(F!=100){curvyObject.setOpacity(B,F)}B.style.top=G+"px";B.style.left=J+"px";I.appendChild(B)};curvyObject.prototype.fillerWidth=function(A){var B=curvyBrowser.quirksMode?0:this.spec.radiusCount(A)*this.borderWidthL;return(this.boxWidth-this.spec.radiusSum(A)+B)+"px"};curvyObject.prototype.errmsg=function(C,D){var B="\ntag: "+this.box.tagName;if(this.box.id){B+="\nid: "+this.box.id}if(this.box.className){B+="\nclass: "+this.box.className}var A;if((A=this.box.parentNode)===null){B+="\n(box has no parent)"}else{B+="\nParent tag: "+A.tagName;if(A.id){B+="\nParent ID: "+A.id}if(A.className){B+="\nParent class: "+A.className}}if(D===undefined){D="warning"}return"curvyObject "+D+":\n"+C+B};curvyObject.prototype.newError=function(A){return new Error(this.errmsg(A,"exception"))};curvyObject.IntToHex=function(B){var A=["0","1","2","3","4","5","6","7","8","9","A","B","C","D","E","F"];return A[B>>>4]+""+A[B&15]};curvyObject.BlendColour=function(L,J,G){if(L==="transparent"||J==="transparent"){throw this.newError("Cannot blend with transparent")}if(L.charAt(0)!=="#"){L=curvyObject.format_colour(L)}if(J.charAt(0)!=="#"){J=curvyObject.format_colour(J)}var D=parseInt(L.substr(1,2),16);var K=parseInt(L.substr(3,2),16);var F=parseInt(L.substr(5,2),16);var C=parseInt(J.substr(1,2),16);var I=parseInt(J.substr(3,2),16);var E=parseInt(J.substr(5,2),16);if(G>1||G<0){G=1}var H=Math.round((D*G)+(C*(1-G)));if(H>255){H=255}if(H<0){H=0}var B=Math.round((K*G)+(I*(1-G)));if(B>255){B=255}if(B<0){B=0}var A=Math.round((F*G)+(E*(1-G)));if(A>255){A=255}if(A<0){A=0}return"#"+curvyObject.IntToHex(H)+curvyObject.IntToHex(B)+curvyObject.IntToHex(A)};curvyObject.pixelFraction=function(H,G,A){var J;var E=A*A;var B=new Array(2);var F=new Array(2);var I=0;var C="";var D=Math.sqrt(E-Math.pow(H,2));if(D>=G&&D<(G+1)){C="Left";B[I]=0;F[I]=D-G;++I}D=Math.sqrt(E-Math.pow(G+1,2));if(D>=H&&D<(H+1)){C+="Top";B[I]=D-H;F[I]=1;++I}D=Math.sqrt(E-Math.pow(H+1,2));if(D>=G&&D<(G+1)){C+="Right";B[I]=1;F[I]=D-G;++I}D=Math.sqrt(E-Math.pow(G,2));if(D>=H&&D<(H+1)){C+="Bottom";B[I]=D-H;F[I]=0}switch(C){case"LeftRight":J=Math.min(F[0],F[1])+((Math.max(F[0],F[1])-Math.min(F[0],F[1]))/2);break;case"TopRight":J=1-(((1-B[0])*(1-F[1]))/2);break;case"TopBottom":J=Math.min(B[0],B[1])+((Math.max(B[0],B[1])-Math.min(B[0],B[1]))/2);break;case"LeftBottom":J=F[0]*B[1]/2;break;default:J=1}return J};curvyObject.rgb2Array=function(A){var B=A.substring(4,A.indexOf(")"));return B.split(", ")};curvyObject.rgb2Hex=function(B){try{var C=curvyObject.rgb2Array(B);var G=parseInt(C[0]);var E=parseInt(C[1]);var A=parseInt(C[2]);var D="#"+curvyObject.IntToHex(G)+curvyObject.IntToHex(E)+curvyObject.IntToHex(A)}catch(F){var H="getMessage" in F?F.getMessage():F.message;throw new Error("Error ("+H+") converting RGB value to Hex in rgb2Hex")}return D};curvyObject.setOpacity=function(F,C){C=(C==100)?99.999:C;if(curvyBrowser.isSafari&&F.tagName!="IFRAME"){var B=curvyObject.rgb2Array(F.style.backgroundColor);var E=parseInt(B[0]);var D=parseInt(B[1]);var A=parseInt(B[2]);F.style.backgroundColor="rgba("+E+", "+D+", "+A+", "+C/100+")"}else{if(typeof F.style.opacity!=="undefined"){F.style.opacity=C/100}else{if(typeof F.style.MozOpacity!=="undefined"){F.style.MozOpacity=C/100}else{if(typeof F.style.filter!="undefined"){F.style.filter="alpha(opacity="+C+")"}else{if(typeof F.style.KHTMLOpacity!="undefined"){F.style.KHTMLOpacity=C/100}}}}}};function addEvent(D,C,B,A){if(D.addEventListener){D.addEventListener(C,B,A);return true}if(D.attachEvent){return D.attachEvent("on"+C,B)}D["on"+C]=B;return false}curvyObject.getComputedColour=function(E){var F=document.createElement("DIV");F.style.backgroundColor=E;document.body.appendChild(F);if(window.getComputedStyle){var D=document.defaultView.getComputedStyle(F,null).getPropertyValue("background-color");F.parentNode.removeChild(F);if(D.substr(0,3)==="rgb"){D=curvyObject.rgb2Hex(D)}return D}else{var A=document.body.createTextRange();A.moveToElementText(F);A.execCommand("ForeColor",false,E);var B=A.queryCommandValue("ForeColor");var C="rgb("+(B&255)+", "+((B&65280)>>8)+", "+((B&16711680)>>16)+")";F.parentNode.removeChild(F);A=null;return curvyObject.rgb2Hex(C)}};curvyObject.format_colour=function(A){if(A!=""&&A!="transparent"){if(A.substr(0,3)==="rgb"){A=curvyObject.rgb2Hex(A)}else{if(A.charAt(0)!=="#"){A=curvyObject.getComputedColour(A)}else{if(A.length===4){A="#"+A.charAt(1)+A.charAt(1)+A.charAt(2)+A.charAt(2)+A.charAt(3)+A.charAt(3)}}}}return A};curvyCorners.getElementsByClass=function(H,F){var E=new Array;if(F===undefined){F=document}H=H.split(".");var A="*";if(H.length===1){A=H[0];H=false}else{if(H[0]){A=H[0]}H=H[1]}var D,C,B;if(A.charAt(0)==="#"){C=document.getElementById(A.substr(1));if(C){E.push(C)}}else{C=F.getElementsByTagName(A);B=C.length;if(H){var G=new RegExp("(^|\\s)"+H+"(\\s|$)");for(D=0;D<B;++D){if(G.test(C[D].className)){E.push(C[D])}}}else{for(D=0;D<B;++D){E.push(C[D])}}}return E};if(curvyBrowser.isMoz||curvyBrowser.isWebKit){var curvyCornersNoAutoScan=true}else{curvyCorners.scanStyles=function(){function B(F){var G=/^[\d.]+(\w+)$/.exec(F);return G[1]}var E,D,C;if(curvyBrowser.isIE){function A(L){var J=L.style;if(curvyBrowser.ieVer>6){var H=J["-webkit-border-radius"]||0;var K=J["-webkit-border-top-right-radius"]||0;var F=J["-webkit-border-top-left-radius"]||0;var G=J["-webkit-border-bottom-right-radius"]||0;var M=J["-webkit-border-bottom-left-radius"]||0}else{var H=J["webkit-border-radius"]||0;var K=J["webkit-border-top-right-radius"]||0;var F=J["webkit-border-top-left-radius"]||0;var G=J["webkit-border-bottom-right-radius"]||0;var M=J["webkit-border-bottom-left-radius"]||0}if(H||F||K||G||M){var I=new curvyCnrSpec(L.selectorText);if(H){I.setcorner(null,null,parseInt(H),B(H))}else{if(K){I.setcorner("t","r",parseInt(K),B(K))}if(F){I.setcorner("t","l",parseInt(F),B(F))}if(M){I.setcorner("b","l",parseInt(M),B(M))}if(G){I.setcorner("b","r",parseInt(G),B(G))}}curvyCorners(I)}}for(E=0;E<document.styleSheets.length;++E){if(document.styleSheets[E].imports){for(D=0;D<document.styleSheets[E].imports.length;++D){for(C=0;C<document.styleSheets[E].imports[D].rules.length;++C){A(document.styleSheets[E].imports[D].rules[C])}}}for(D=0;D<document.styleSheets[E].rules.length;++D){A(document.styleSheets[E].rules[D])}}}else{if(curvyBrowser.isOp){for(E=0;E<document.styleSheets.length;++E){if(operasheet.contains_border_radius(E)){C=new operasheet(E);for(D in C.rules){if(!isNaN(D)){curvyCorners(C.rules[D])}}}}}else{curvyCorners.alert("Scanstyles does nothing in Webkit/Firefox")}}};curvyCorners.init=function(){if(arguments.callee.done){return}arguments.callee.done=true;if(curvyBrowser.isWebKit&&curvyCorners.init.timer){clearInterval(curvyCorners.init.timer);curvyCorners.init.timer=null}curvyCorners.scanStyles()}}if(typeof curvyCornersNoAutoScan==="undefined"||curvyCornersNoAutoScan===false){if(curvyBrowser.isOp){document.addEventListener("DOMContentLoaded",curvyCorners.init,false)}else{addEvent(window,"load",curvyCorners.init,false)}};

/*
 * Image preview script 
 * powered by jQuery (http://www.jquery.com)
 * 
 * written by Alen Grakalic (http://cssglobe.com)
 * 
 * for more info visit http://cssglobe.com/post/1695/easiest-tooltip-and-image-preview-using-jquery
 *
 */
 
this.imagePreview = function(){	
	/* CONFIG */
		
		yOffset = 500;
		xOffset = 30;
		
		// these 2 variable determine popup's distance from the cursor
		// you might want to adjust to get the right result
		
	/* END CONFIG */
	$("a.preview, img.image_preview").hover(function(e){
		this.t = this.title;
		this.title = "";	
		//alert(this.href);
		var c = (this.t != "") ? "<br/>" + this.t : "";
		$("body").append("<p id='preview' style='z-index: 1000'><img src='"+ (this.href ? this.href : this.src) +"' alt='Image preview' />"+ c +"</p>");								 
		var height = parseInt($('#preview').css('height'));
		// if(height > 700) yOffset += 300;
		// $("#preview").append("<p> h ="+ height +"</p>");								 
		$("#preview")                                                         
			.css("top",(e.pageY - yOffset) + "px")
			.css("left",(e.pageX + xOffset) + "px")
			.fadeIn("fast");						
    },
	function(){
		this.title = this.t;	
		$("#preview").remove();
    });	
	// $("a.preview").mousemove(function(e){
	// 	$("#preview")
	// 		.css("bottom",(e.pageY - yOffset) + "px")
	// 		.css("left",(e.pageX + xOffset) + "px");
	// });			
};

function ckeditor_enable(id) {
 CKEDITOR.replace(id,
 {
  // toolbar : 'Basic',
  filebrowserBrowseUrl :      '/ckeditor/ckfinder/ckfinder.html',
  filebrowserUploadUrl :      '/ckeditor/ckfinder/core/connector/php/connector.php?command=QuickUpload&type=Images',
 	filebrowserImageBrowseUrl : '/ckeditor/ckfinder/ckfinder.html?type=Images',
 	filebrowserFlashBrowseUrl : '/ckeditor/ckfinder/ckfinder.html?type=Flash'
 });
}

hotkeyDown = false;
function hotkey_edit() {
  var ctrlKey = 17, shiftKey = 16, f2Key=113, vKey = 86, cKey = 67;
  $(document).keydown(function(e) {
    if (e.keyCode == ctrlKey || e.keyCode == shiftKey || e.keyCode == f2Key) $(".ie_edit_link").toggle();
    //hotkeyDown = true;
  }).keyup(function(e) {
    // if (e.keyCode == ctrlKey || e.keyCode == shiftKey|| e.keyCode == f2Key) $(".ie_edit_link").hide();
  });

  // below can be used to disallow copy/paste 
  // $(".no-copy-paste").keydown(function(e) {
  //   if (ctrlDown && (e.keyCode == vKey || e.keyCode == cKey)) return false;
  // });
}

function facebook_wall(user, limit, offset) {  
  var ajax_url = '/home/ajax/facebook.php?user=' + user + '&limit=' + limit + '&offset=' + offset;
  //alert(ajax_url);
  $("#facebook_wall").load(ajax_url);    
}

// for now: non-generic version of article list
function news_list(search, options) {
  var ajax_url = '/home/ajax/cms.php?obj_type=news&search=' + array2json(search) + '&limit=' + options.limit + '&offset=' + options.offset;
  var ajax_url = '/home/ajax/cms.php?obj_type=news&search=' + array2json(search) + '&options=' + array2json(options); 
  //alert(dump(search) + dump(options) + ajax_url);
  //alert("limit=" + options.limit + " offset=" + options.offset + " " + array2json(search));
  $("#site_news_list").load(ajax_url);    
}

// tbc: generic function for listing articles
function article_list(div_id, obj_type, search, sort, fields, limit, offset, handler) {  
  $("#" + div_id).load(ajax_url);    
}

// same as find_objects in back-end
function find_objects(obj_type, search, sort, fields, limit, offset, handler) {  
  ajax_url = "/" + (unauthenticated ? "home" : "admin") + "/app_data.php?oper=list&obj_type=" + obj_type + "&id=" + id + "&reload=" + reload_bool;

  if(search) ajax_url += "&search=" + array2json(search);
  if(fields) ajax_url += "&fields=" + array2json(fields);
  if(sort) ajax_url += '&sort=' + sort;
  if(limit) ajax_url += '&limit=' + limit;
  if(offset) ajax_url += '&offset=' + offset;
  if(handler) ajax_url += '&handler=' + handler;

  alert(ajax_url);
  $dialog.load(ajax_url, data, function (responseText) {
    alert(dump(responseText));
    //.ckeditor();
  });                                    
  
}

function facebook_wall_js(div_id, user, token, limit, offset) {
  $('#' + div_id).facebookWall({
		id: user,
		access_token: token,
		limit: limit,
		offset: offset
	});
}


