﻿$(document).ready(function() {
  initIE();
  
  initDashboard();
  initExercise();
  initExerciseDetails();
  initExercises();
  // [MSc] OBSOLETE
  //initHome();
  initResults();
  initSearch();
  initScrolling();
  initTest();
});


var initIE = function() {
  if ($.browser.msie && parseInt($.browser.version.substr(0,1)) <= 7) {
    $("#css_ie").attr({ href: "/resources/css/default.ie7.css" });
  }
};

var _truth = false;
var _condition = false;
var initDashboard = function() {
  // Show disabled button by default
  $(".submit_mybooks").css({ "display": "none" });
  $(".submit_mybooks_disabled").css({ "display": "inline-block" });
  
  $(".agree").bind("click", function() {
    if ($("#agree_truth").attr("checked") && $("#agree_conditions").attr("checked")) {
      $(".submit_mybooks button").removeAttr("disabled");
      $(".submit_mybooks").css({ "display": "inline-block" });
      $(".submit_mybooks_disabled").css({ "display": "none" });
    } else {
      $(".submit_mybooks").css({ "display": "none" });
      $(".submit_mybooks_disabled").css({ "display": "inline-block" });
      $(".submit_mybooks button").attr("disabled", "disabled");
    }
  });
  
/*
  $("a.terms").bind("click", function() {
    var href = $(this).attr("href");
    var title = $(this).attr("title");
    return showDialog({url: href, title: title, height: "65%", width: "700px" });
  });
*/
  $('#search_box').data('timeout', null).keyup(function() {
    clearTimeout($(this).data('timeout'));
    //$(this).data('timeout', setTimeout('filterBooks(\"' + $(this).val() + '*\")', 250));
    $(this).data('timeout', setTimeout('filterBooks(\"' + $(this).val() + '\", false)', 250));
  });

  $("#search_button").bind("click", function() {
    filterBooks($('#search_box').val(), false);
    return false;
  });

  $("#clear_button").bind("click", function() {
    $('#search_box').val("");
    filterBooks("", false);
    return false;
  });
  
  $("ul.alpha li a").bind("click", function() {
    var val = $("span", $(this)).text();
    filterBooks(val, true);
    return false;
  });
  
  $("#submit_mybooks").bind("click", function() {
    var mybooks = document.getElementById("mybooks").xfElement.doc.getElementsByTagName("mybooks");
    $(".select_books :checkbox").each(function() {
      if (!$(this).attr("disabled") && !$(this).hasClass("agree")) {
        if ($(this).attr("checked")) {
          // Get id from rel attr
          var id = $(this).attr("rel");
          var bid;
          if (typeof document.createElementNS != 'undefined') {
            // Use createElementNS where possible
            bid = document.createElementNS("", "bookid");
            bid.appendChild(document.createTextNode(id));
          } else {
            // Use clone node in IE!
            bid = mybooks[0].firstChild.cloneNode(false);
            // Simple  but works!
            bid.text = id;
          }
          // Add bookid to instance)
          mybooks[0].appendChild(bid);
        }
      }
    });
    // submit submission
    if (submission = document.getElementById('save_mybooks')) {
      XMLEvents.dispatch(submission, "xforms-submit");
      // submission.xfElement.submit();
      // Give the browser a little time to process the submission before continuing...
      // setTimeout(function() { document.location.href = "/app/home/getstarted"; }, 250);
    }
    return false;
  });
};

function disableCheckedBooks() {
  $(".select_books input").each(function() {
    if (!$(this).attr("disabled") && !$(this).hasClass("agree")) {
      if ($(this).attr("checked")) {
        $(this).attr("disabled", "disabled");
      }
    }
  });
};

var filterBooks = function(val, startWithOnly) {
  var all_books = $(".select_books tr");

  var qry = $.trim(val.toLowerCase());
  if (qry == "") {
    // If query is empty show all
    all_books.show();
    $(".conditions").show();
    $(".noresults").hide();
    return;
  } else {
    // else hide all rows first
    all_books.hide();
  }
  
  //var books = $(".xforms-label", books);
  var books = $("label", books);
  var cnt = 0;
  // Then show all that comply to search
  books.each(function(i) {
    var title = $(this).text().toLowerCase();
    //var title = $(".xforms-value", $(this)).text().toLowerCase();
    if (qry == "" || (startWithOnly ? title.startsWith(qry) : (title.indexOf(qry) > -1))) {
      $(this).parents("tr:not('.conditions')").show();
      cnt++;
    }
  });
  
  if (cnt == 0) {
    $(".conditions").hide();
    $(".noresults").show(); 
  } else {
    $(".conditions").show();
    $(".noresults").hide();
  }
};

var filterBooksXForms = function(val) {
  // Get search element from XForms instance
  var elSearch = document.getElementById('request-context').xfElement.doc.getElementsByTagName('search')[0];
  // Get submission
  var submission = document.getElementById('search_mybooks');
  // Make sure both element and submission exist
  if (elSearch && submission) {
    // clear firstchar
    $(elSearch).find("firstchar").text("");
    // set query text
    $(elSearch).find("query").text(val);
    // submit submission
    submission.xfElement.submit();
  }
};

var initExercise = function() {
  $(".invoke-keywords").bind("click", function() {
    $(".keyword-container").show();
    return false;
  });
  $(".close", ".keyword-container").bind("click", function() {
    $(".keyword-container").hide();
    return false;
  });
};
  
var initExerciseDetails = function() {
  // Trick to make it work in IE as well (probably defers the function a bit)
  setTimeout('initExerciseDetailsNewRating()', 0);
  setTimeout('initExerciseDetailsCurrentRating()', 0);
};

var initExerciseDetailsCurrentRating = function() {
  // Show (disabled) rating stars for existing comments/ratings
  $(".xforms-value", ".current-rating").each(function(idx, item) {
    var rate = parseInt($(this).html());
    if (!isNaN(rate)) {
      // Since we'll be using half stars as well, we need to double the rate value
      var rateValue = rate * 2;
      // Create placeholder div
      var d = $("<div/>");
      // Add 10 stars (1 for each half rating point)
      for(i = 1; i <= 10; i++) {
        // Create new radio button
        var r = $("<input type='radio'>").attr("name", "r-" + idx).attr("value", i).attr("title", rate);
        // Checked radio with current value
        if (i === rateValue) $(r).attr("checked", "checked");
        // Add radio button to div
        $(r).appendTo(d);
      }
      // Apply rating (including half stars and in disabled (view only) mode
      $("input", $(d)).rating({ half: true }).rating("disable");
      // Clear current contents and add rating container
      $(this).empty().append(d);
    }
  });
};

var initExerciseDetailsNewRating = function() {
  // Show rating stars for new rating
  $("span.xforms-value", ".new-rating").each(function(idx, item) {
    // Create placeholder div
    var d = $("<div/>").addClass("rating-container");
    // Add 5 stars (1 for each rating point)
    var t = $(".xforms-item-label", $(item));
    for(i = 1; i <= 5; i++) {
      //alert("t=" + $(t[i-1]).text());
      // Create new radio button
      var r = $("<input type='radio'>").attr("name", "r-" + idx).attr("value", i).attr("title", $(t[i-1]).text());
      // Add radio button to div
      $(r).appendTo(d);
    }
    $("<span/>").addClass("rating-title").appendTo(d);

    $("input", $(d)).rating({ required: true, 
      callback: function(value, link){
        // Get search element from XForms instance
        var elInst = document.getElementById('data_comment').xfElement.doc.getElementsByTagName('rate')[0];
        // Make sure element exists
        if (elInst) {
          // set rating value
          $(elInst).text(value);
        }
      }, 
      focus: function(value, link) {
        $(this).siblings(".rating-title").html(" " + $(this).attr("title"));
      },
      blur: function(value, link) {
        $(this).siblings(".rating-title").empty();
      }
    });
    // Hide current contents and add rating container
    $(this).hide().parent().append(d);
  });
}

var initExercises = function() {
  $("#exercises").sortable({
    axis: "y",
    handle: 'span.handle',
    helper: "clone",
    update: function(event, ui) {
      // get dragged item's id
      var currentid = ui.item.attr("id");
   	  // get id of li next to current one
      var nextid = $("#" + currentid).next("li").attr("id");
      // get xforms test instance container
      var exercises = document.getElementById("data-new-test").xfElement.doc.getElementsByTagName('exercises')
      var parent = exercises[0];
      var currentNode = null;
      var nextNode = null;
      // find the id elements to sort
      $("id", $(parent)).each(function(i, obj){
    	  if($(obj).text() == currentid) {
    		  currentNode = obj; 
    	  }
    	  if($(obj).text() == nextid) {
    		  nextNode = obj; 
    	  }
        });
      // do the sorting
      if (nextNode){
        parent.insertBefore(currentNode,nextNode);
      } else {
        parent.appendChild(currentNode);
      }
      
      $("#exercises .cell.no").each(function(index, item) {
        $(item).text((index + 1) + ". ");
      });
    }
  });
  
  $("#exercises a.view").bind("click", function() {
    var href = $(this).attr("href");
    var title = $(this).attr("title");
    return showDialog({url: href, title: title, height: "80%", width: "780px" });
  });

  $("#exercises .delete a").bind("click", function() {
		var href = $(this).attr("href");
		$(this).attr("href", "#");
		var exercises = document.getElementById("data-new-test").xfElement.doc.getElementsByTagName('exercises');
		var parent = exercises[0];
		var remove = [];
    $("id", $(parent)).each(function(i, obj){
  	  if($(obj).text() == href) {
  		  remove.push(obj); 
  	  }
    });
		for (var i=remove.length-1; i >= 0; --i) {
		  parent.removeChild(remove[i]);
		}
		// remove object from list
    $("#exercises li#"+href).remove();
    return false;
  });
};

/* [MSc] OBSOLETE */
/*
var initHome = function() {
  $("a.showdialog").bind("click", function() {
    var href = $(this).attr("href");
    var title = $(this).attr("title");
    return showDialog({url: href, title: title, height: "250px", width: "500px"});
  });
};
*/

var initResults = function() {
  // If facet "booktype" is defined, select relevant tab:
  //booktype=mybooks, other, all
  var booktype = $.getUrlVar("booktype");
  switch(booktype) {
    case "all": 
    case "other":
      break;
    default:
      booktype = "mybooks";
      break;
  }
  $("#books-container").addClass(booktype);
  $("#tabs_books li").removeClass("current");
  $("#tab_"+booktype, "#tabs_books").addClass("current");
  
  $("#tabs_books li a, #books-container .show_all").bind("click", function() {
    var booktype = $(this).attr("hash").replace("#", "");
    var url = getXFormsUrl("request-context", "resultapp", new Array("booktype", "start"));
    var sep = url.indexOf("?") < 0 ? "?" : "&";
    url = url.concat(sep, "booktype=", booktype);
    document.location.href = url;
    return false;
  });
  
 // Use the each() method to gain access to each of the elements attributes
  $("a.order").each(function() {
    var rel = $(this).attr("rel").split("$$");
    var isbn = rel[0];
    var title = rel[1];
    var url = "http://www.noordhoffuitgevers.nl/wps/portal/ho/catalogus?searchitem=" + isbn;
    $(this).qtip({
      content: 
        '<div class="noaccess">' +
          '<img src=\'/resources/img/books/' + isbn + '.jpg\' alt=\'\' height=\'105\' width=\'72\' />' +
          '<p>To access this content, you need to prescribe this book.</p>' +
          '<p>Order you <a href=\'' + url + '\' target=\'_blank\'>evalution copy</a> of <em>' + title + '</em> now.</p>' +
        '</div>',
      position: {
        adjust: { 
          mouse: false,
          y: -5
        },
        target: 'mouse',
        corner: {
          tooltip: 'bottomMiddle'
        }
      },
      hide: {
        fixed: true // Make it fixed so it can be hovered over
      },
      style: {
        border: {
          color: "#777",
          width: 3
        },
        tip: true // Give it a speech bubble tip with automatic corner detection
      }
    });
  });

  // Click on paging link opens new url based on XForms params
  $("#pages li a").bind("click", function() {
    var start = $(this).attr("hash").replace("#", "");
    var url = getXFormsUrl("request-context", "resultapp", new Array("start"));
    var sep = url.indexOf("?") < 0 ? "?" : "&";
    url = url.concat(sep, "start=", start);
    document.location.href = url;
    return false;
  });
  // Change of page-length opens new url based on XForms params
  $("#results-page-length").bind("change", function() {
    var url = getXFormsUrl("request-context", "resultapp", new Array("page-length", "start"));
    var sep = url.indexOf("?") < 0 ? "?" : "&";
    url = url.concat(sep, "page-length=", $(this).val());
    document.location.href = url;
    return false;
  });
  // Open details based on XForms params
  $("li.result a.details, #nav_doc .prev, #nav_doc .next").bind("click", function() {
    var start = $(this).attr("hash").replace("#", "");
    var url = getXFormsUrl("request-context", "exercisedetailsapp", new Array("page-length", "start"));
    var sep = url.indexOf("?") < 0 ? "?" : "&";
    url = url.concat(sep, "page-length=", 1);
    url = url.concat("&", "start=", start);
    document.location.href = url;
    return false;
  });

  // Set facet links (moved to "XForms-ready!)
  updateFacets();
  
  // Set facet links
  $("#nav-facets h4").css({ cursor: "pointer" });
  $("#nav-facets h4").bind("click", function(e) {
    e.preventDefault();
    $(this).toggleClass("collapsed");
  });
  
  $("#nav-sort a").bind("click", function() {
    var sort = $(this).attr("hash").replace("#", "");
    var url = getXFormsUrl("request-context", "resultapp", new Array("sort"));
    var sep = url.indexOf("?") < 0 ? "?" : "&";
    url = url.concat(sep, "sort=", sort);
    document.location.href = url;
    return false;
  });
  
  $("#breadcrumbs a.return").bind("click", function() {
    var url = getXFormsUrl("request-context", "bookexerciseapp", new Array("page-length", "start", "bookid", "chapterid"));
    document.location.href = url;
    return false;
  });
  
  // Init readonly rating in result list
  $("input.ster", "p.rating").rating({ half: true }).rating("disable");

  // Add/remove exercises from/to active test
  $(".result-add-remove input[type='checkbox']").bind("click", function() {
    if (submission = document.getElementById("update-test")) {
      // Put action & id in instance and submit
      setXFormsValue("request-context", "request", "action", $(this).attr("checked") ? "add" : "del");
      setXFormsValue("request-context", "request", "doc-id", $(this).val());
      XMLEvents.dispatch(submission,"xforms-submit");
    }
  });
  // Add all (visible) exercises to active test
  $(".add-remove.all.add.enabled").bind("click", function() {
    if (submission = document.getElementById("update-test-all")) {
      // Put action in instance & submit
      setXFormsValue("request-context", "request", "action", "add-all");
      XMLEvents.dispatch(submission, "xforms-submit");
    }
  });
  // Remove all (visible) exercises from active test
  $(".add-remove.all.remove.enabled").bind("click", function() {
    if (submission = document.getElementById("update-test-all")) {
      // Put action in instance & submit
      setXFormsValue("request-context", "request", "action", "remove-all");
      XMLEvents.dispatch(submission, "xforms-submit");
    }
  });
};

var updateFacets = function() {
  $("#nav-facets a").each(function() {
    var facet = $(this).attr("hash").replace("#", "").split('=');
    var name = facet[0];
    var value = facet[1];
    var instanceValue = getXFormsParamValue("request-context", name);
    if (name != "booktype") {
      if (instanceValue.length == 0)
        $(this).removeClass("current");
      else
        $(this).addClass("current");
    }

    $(this).bind("click", function() {
      var url = getXFormsUrl("request-context", "resultapp", new Array(name));
      var sep = url.indexOf("?") < 0 ? "?" : "&";
      if (instanceValue.length == 0)
        url = url.concat(sep, name, "=", escape(value));
      document.location.href = url;
      return false;
    });
  });
};

var updateResultsSelections = function() {
	$(".result-add-remove input[type='checkbox']").each(function() {
    var id = $(this).val();
    if (getXFormsValueExists("data-test", "exercises", "id", id)) {
      $(this).attr("checked", "checked");
    } else {
      $(this).removeAttr("checked");
    }
  });
  var exerciselist = getXFormsValues("data-exerciselist","exercise","id");
  var testlist = [];
  $.each(getXFormsValues("data-test","exercises","id"), function (index, value) {
      if ($.inArray(value, exerciselist) >= 0) {
    	  testlist.push(value);
	    }
	});
  if (exerciselist.length == testlist.length) {
    $(".add-remove.all.add.enabled").hide();
    $(".add-remove.all.remove.enabled").show();
  } else {
    $(".add-remove.all.add.enabled").show();
    $(".add-remove.all.remove.enabled").hide();
  }
};

var initSearch = function() {
  $(".button", ".srch_form").bind("click", function() {
    $(this).parent("form").submit();
    return false;
  });
}

var initScrolling = function() {
  if (!$.browser.msie || parseInt($.browser.version.substr(0,1)) >= 8) {
    var _offset = 142;
    window.onscroll = function() {
      if (document.documentElement.scrollTop > _offset || self.pageYOffset > _offset) {
        $("body").addClass("msc-sticky");
      } else if (document.documentElement.scrollTop < _offset || self.pageYOffset < _offset) {
        $("body").removeClass("msc-sticky");
      }
    }
  }
};

var initActiveTest = function() {
  var name = getXFormsValue("data-test", "test", "name");
  if ($("#link_activetest")) {
	  $("#link_activetest").attr("title", name);
	  if (name.length > 30)
		  $("#link_activetest .xforms-value").text(name.substring(0, 27) + '...');
  }
  if ($("#show_activetest") && name != '')
	  $("#show_activetest").show();
  else
	  $("#show_activetest").hide();
}

var initTest = function() {
  $(".test_export").bind("click", function() {
    return showDialog({ url: $(this).attr("href"), title: $(this).attr("title"), height: "550px", width: "650px" });
  });
  initActiveTest();
};

var reloadActiveTest = function() {
  highlightExercises();
  top.document.location.reload();
};

var showExport = function(id, _title) {
  var _url = "/app/test/show-export/" + id;
  return showDialog({ url: _url, title: _title, height: "550px", width: "650px", onClosed: function() { reloadActiveTest(); } });
}

var showDialog = function(options) {  /*_url, _title, _height, _width, _onOpen, _onClosed) {*/
  if (options == null) options = {};
  if (!options.height || options.height === 0) options.height = "95%";
  if (!options.width || options.width.length === 0) options.width = "680px";
  if (typeof(options.iframe) == "undefined") options.iframe = true;
  /* Set colorbox options */
  var colorbox_options = {
    height: options.height,
    width: options.width,
    overlayClose: false,
    iframe: options.iframe,
    title: options.title,
    href: options.url,
    onOpen: options.onOpen,
    onClosed: options.onClosed,
    onLoad: options.onLoad
  };
  /* Call colorbox */
  $.colorbox(colorbox_options);
  /* return false (to prevent href to open) */
  return false;
}

/* multi choice handling, changes input to radio and adds event handling */
var radioAnswers = function() {
  $(".status-radio").each(function(index) {
	  var position = index;
	  var radio = $("input", this)[0];
	  if (radio.type == "radio") {
		  $(radio).click(function() {
			  if ($(this).is(":checked")) {
				  var inst = document.getElementById("exercise").xfElement;
				  var answers = inst.doc.getElementsByTagName('answer');
				  $(".status-radio").each(function(index) {
					  var radio = $("input:radio", this)[0];
					  radio.value == 'distract'
					  radio.checked = false;
					  $(answers[index]).attr("status","distract");
				  });
				  this.value = 'correct';
				  this.checked = true;
				  var models = xforms.models;
				  xforms.openAction();
				for (var i=0; i < models.length; ++i) {
					var model = models[i];
					var modelId = model.element.id;
					if (modelId != 'xf-model-config' && modelId != 'xf-model-extensions') {
						XMLEvents.dispatch(model, "xforms-recalculate");
					}
				}
				  xforms.refresh();
				  xforms.closeAction();
			  }
		  });
	  };
  });
  return false;
}

/* Retrieves url + params from instance and returns new url */
var getXFormsUrl = function(instanceid, urltype, excludes) {
  // Get instance by instanceid + doc
  var inst = document.getElementById(instanceid);
  var doc = $(inst.xfElement.doc);
  // Get url by urltype
  var url = $("url[type=" + urltype + "]", doc).text();

  // Get params
  var params = $('params', doc);
  var cnt = 0;
  $("*", params).each(function(index) {
    // Get name + value and determine ? vs &amp;
    var name = $(this).get(0).tagName;
    if (excludes.indexOf(name) < 0) {
      var value = $(this).text();
      if (value.length > 0) {
        var sep = (cnt == 0) ? "?" : "&";
        // Tie it all together
        url = url.concat(sep, name, "=", value);
        cnt++;
      }
    }
  });
  // Return url
  return url;
}

/* Retrieves url + params from instance and returns new url */
var getXFormsParamValue = function(instanceid, name) {
  return getXFormsValue(instanceid, 'params', name);
};

/* Retrieves value from instance for given instanceid, elementname and name */
var getXFormsValues = function(instanceid, elementname, name) {
  // Get instance by instanceid + doc
  var inst = document.getElementById(instanceid);
  if (inst == null) return "";
  var doc = $(inst.xfElement.doc);
  // Get elements
  var elements = $(elementname, doc);
  var values = $(name, elements);
  var ret = [];
  $(values).each(function(index) {
    var val = $(this).text();
    if (val.length > 0)
      ret.push(val)
  });
  return ret;
};

/* Retrieves value from instance for given instanceid, elementname and name */
var getXFormsValue = function(instanceid, elementname, name) {
  // Get instance by instanceid + doc
  var inst = document.getElementById(instanceid);
  if (inst == null) return "";
  var doc = $(inst.xfElement.doc);
  // Get elements
  var elements = $(elementname, doc);
  var values = $(name, elements);
  var ret = "";
  $(values).each(function(index) {
    var val = $(this).text();
    if (val.length > 0)
      ret = val;
  });
  return ret;
};

/* Retrieves value from instance for given instanceid, elementname and name */
var getXFormsValueExists = function(instanceid, elementname, name, value) {
  // Get instance by instanceid + doc
  var inst = document.getElementById(instanceid);
  if (inst == null) return false;

  var doc = $(inst.xfElement.doc);
  // Get elements
  var elements = $(elementname, doc);
  var values = $(name, elements);
  var ret = false;
  $(values).each(function(index) {
    var val = $(this).text();
    if (val == value) {
      ret = true;
    }
  });
  return ret;
};

var setXFormsValue = function(instanceid, elementname, name, value) {
  // Get instance by instanceid + doc
  var inst = document.getElementById(instanceid);
  var doc = $(inst.xfElement.doc);
  // Get elements
  var elements = $(elementname, doc);
  var values = $(name, elements);
  $(values).each(function(index) {
    $(this).text(value);
  });
};

var toggleBookSearchControls = function(shown) {
  if (shown == 0) {
    $(".hasresults").hide();
    $(".noresults").show();
    $("input.submit_mybooks").attr("disabled", "true");
  } else {
    $(".hasresults").show();
    $(".noresults").hide();
    $("input.submit_mybooks").removeAttr("disabled");
  }
}

$.extend({
  getUrlVars: function(){
    var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++) {
      hash = hashes[i].split('=');
      vars.push(hash[0]);
      vars[hash[0]] = hash[1];
    }
    return vars;
  },
  getUrlVar: function(name){
    return $.getUrlVars()[name];
  }
});

jQuery.fn.flash = function() {
  var el = $(this[0]);            // Your element
  try {
      var args = arguments[0] || {};  // Your object of arguments
      var colorFrom = args.colorFrom || "#0f0";
      var colorTo = args.colorTo || "#fff";
      var timeout = args.timeOut || 500;
      return el.stop().animate({ backgroundColor: colorFrom }, timeout).delay(2 * timeout).animate({ backgroundColor: colorTo }, timeout);
  } catch (e) { }
  return el;
};

/* Scroll document to position of element with given selector */
var scroll = function(selector) {
  try {
    var destination = selector ? $(selector).offset().top : 0;
    $("html:not(:animated),body:not(:animated)").animate({ scrollTop: destination - 20 }, 250);
  } catch(exception) {
    // do nothing here, if animation can't work, just jump to anchor
  }
  return false;
}

var dummy = function() {
  alert("dummy");
}

var highlightExercises = function() {
  var _colorFrom = "#0f0";
  var _colorTo = "#fff";

  $(".activetest").flash({ colorFrom: _colorFrom, colorTo: _colorTo }); 
}

//Extend string with trim() function
String.prototype.trim = function() {
  return this.replace(/(^\s+|(\s+$))/g,'');
}
//Extend string with startsWith function
String.prototype.startsWith = function(str) {
  return (this.match("^"+str)==str);
}
// Extend string with endWith function
String.prototype.endsWith = function(str) {
  return (this.match(str+"$")==str);
}

/* Dhoohh, damn you IE: Doesn't support indexOf on arrays so add it when this applies */
if(!Array.indexOf){
  Array.prototype.indexOf = function(obj){
    for(var i=0; i<this.length; i++){
      if(this[i]==obj){
        return i;
      }
    }
    return -1;
  }
}

/*
var delay = (function(){
  var timer = 0;
  return function(callback, ms){
    clearTimeout (timer);
    timer = setTimeout(callback, ms);
  };
})();
*/
