 $(document).ready(function() {
      //Don't run the script if mdetect.js has confirmed that we're running on a iPhone-type unit.
      if(typeof isTierIphone == 'undefined' || (!isTierIphone && !DetectIpad())) {
        $(".dragDropGrid, .dragSortGrid").find("table:last").each(function(i) {
            var drag = new DragDropGrid(this);
			if(drag.activated) {
				$(this).parents(".dragDropGrid, .dragSortGrid").addClass("dragActivated");
			}
        });
      }
 });
 
function DragDropGrid(gridObject) {
  this.oldGridObject = gridObject;
  this.questionId = 0;
  this.answerAlternatives = new Object;
  this.gridItems = new Object;
  this.gridItemsToInsert = new Object;
  this.gridItemsHeader = null;
  this.activated = false;
  this.singleSort = false;
  this.maxItems = -1;
   
  this.initiate();
  this.printDragDropObjects();

}
 
DragDropGrid.prototype.initiate = function() {
    var rows = $(this.oldGridObject).children("thead,tbody").children("tr");
    var firstRow = $(rows).first();
    var otherRows = $(rows).has("input");

    var answerAlternativeInputs = $(otherRows).first().children("td,th").not(":first-child").has("input").find("a,input[type='text']");
    var answerColumns = $(answerAlternativeInputs).length * -1;    
    var answerAlternativeTextCells = $(firstRow).children("td,th").slice(answerColumns);

    var gridItemHeader = $(firstRow).children("td:first-child,th:first-child");
    if($(gridItemHeader).text().trim().length > 0) this.gridItemsHeader = $(gridItemHeader).get(0);
    var gridItemTextCells = $(otherRows).children("td:first-child");
    var gridItemInputs = $(otherRows).children("td:last-child").find("a,input[type=text]");
    var checkedInputs = $(otherRows).children("td").has("input:checked").find("a");
	
    if(answerAlternativeTextCells.length === 1 && answerAlternativeInputs.length === 1) this.singleSort = true;
	//if(this.singleSort) alert("singleSort");
	if(this.singleSort) checkedInputs = $(otherRows).children("td").find('input:text[value!=""]');
	
    this.setQuestionId($(answerAlternativeInputs).last().get()[0]);
    this.setAnswerAlternatives($(answerAlternativeTextCells).get(), $(answerAlternativeInputs).get());
    this.setGridItems($(gridItemTextCells).get(), $(gridItemInputs).get());
    this.setInitialAnswers($(checkedInputs).get());
    
	var newMax = this.maxItems;
	firstRow.parents('.dragDropGrid[class*="maxItems_"]').first().each(function() {
		var a = /maxItems_(\d)/.exec(this.className);
		if(a.length >= 2) newMax = Number(a[1]);
	});
	this.maxItems = newMax;
    $(this.oldGridObject).css("display", "none");
	this.activated = true;
}

DragDropGrid.prototype.printDragDropObjects = function() { 
  var answerAlternatives = this.createDroppableAnswerAlternatives();
  $(this.oldGridObject).after(answerAlternatives);
  
  var gridItems = this.createDraggableGridItems();
  $(answerAlternatives).before(gridItems);
 
  var div = document.createElement("div");
  $(div).css("clear", "both");
  $(answerAlternatives).after(div);
  
  var uniqueDropClassName = "dropList" + this.questionId;
  $("."+uniqueDropClassName).sortable( "option", "connectWith", '.'+uniqueDropClassName );
  var questionId = this.questionId;

  $(".answerAlternativeLists .answerAlternativeBox").each(function() {
		updateMax(this, questionId);
  });
}

DragDropGrid.prototype.createDroppableAnswerAlternatives = function() {
  var div = document.createElement("div");
  $(div).addClass("answerAlternativeLists");
  var uniqueDropClassName = "dropList" + this.questionId;
  for(var i in this.answerAlternatives) {
    var ul = document.createElement("ul");
    $(ul).addClass("answerAlternativeBox");
    var li = document.createElement("li");
    li.innerHTML = this.answerAlternatives[i].innerHTML; //TODO: Do cloneNode(true);
    li.className = this.answerAlternatives[i].className;
    $(li).addClass("answerAlternativeText");
    ul.appendChild(li);
    this.createDraggableGridItemsFromRidArray(this.answerAlternatives[i].initialGridItems, ul);
    ul.answerId = this.answerAlternatives[i].answerId;
	ul.maxItems = this.maxItems;
    div.appendChild(ul);
    $(ul).sortable( { items: 'li:not(.answerAlternativeText)', receive: itemDropped, deactivate: itemReorder, start: dragSortStart, stop: dragSortEnd, over: dragOverList, out: dragOutList } ).addClass("answerAlternativeDropList").addClass(uniqueDropClassName);
  }
  return div;
}

DragDropGrid.prototype.createDraggableGridItems = function() {
  var ul = document.createElement("ul");
  ul.answerId = 0;
  if(this.gridItemsHeader) {
    var li = document.createElement("li");
    li.innerHTML = this.gridItemsHeader.innerHTML;
    li.className = this.gridItemsHeader.className;
    $(li).addClass("gridItemsHeader");
    ul.appendChild(li);
  }
  var ridArray = new Array();
  for(var i in this.gridItemsToInsert) {
	if(this.gridItemsToInsert[i].tagName) {
		var key = i;
		key.origOrder = this.gridItemsToInsert[i].origOrder ? this.gridItemsToInsert[i].origOrder : 0;
		ridArray.push(key);
	}
  }
  this.createDraggableGridItemsFromRidArray(ridArray, ul);
  delete this.gridItemsToInsert;
  this.gridItemsToInsert = new Object;
  var uniqueDropClassName = "dropList" + this.questionId;
  $(ul).sortable( { items: 'li:not(.gridItemsHeader)', receive: itemDropped, deactivate: itemReorder, start: dragSortStart, stop: dragSortEnd, dragover: dragOverList, out: dragOutList } ).addClass("defaultDropList").addClass(uniqueDropClassName);
  return ul;
}
DragDropGrid.prototype.createDraggableGridItemsFromRidArray = function(ridArray, parent) {
  var toInsert = new Array();
  for(var i=0; i<ridArray.length; i++) {
    var gridItem = this.gridItemsToInsert[ridArray[i]];
    toInsert.push(gridItem);
    delete this.gridItemsToInsert[ridArray[i]];
  }
  toInsert.sort(sortByOrigOrder);
  for(var x=0; x<toInsert.length; x++) {
    this.createAndAppendDraggableGridItem(toInsert[x], parent);
  }
}
DragDropGrid.prototype.createAndAppendDraggableGridItem = function(gridItem, parent) {
    var li = document.createElement("li");
    li.innerHTML = gridItem.innerHTML; //TODO: Do cloneNode(true);
    li.className = gridItem.className;
    li.rowId = gridItem.rowId;
    li.questionId = gridItem.questionId;
    $(li).addClass("draggableGridItem");
    addDragHoverClasses(li);
    parent.appendChild(li);
}

function itemDropped(event, ui) {
  var item = $(ui.item).get(0);
  var list = this;
  var answerId = list.answerId == 0 ? 1 : list.answerId;
  var setValueName = "setvalueQ"+item.questionId+"."+item.rowId+":"+answerId;
  var setValueLink = $("A[name='"+setValueName+"']");
  if(list.answerId == 0) {
    $(setValueLink).parents("tr").first().find("input:checked,input:text").each(function () {
       if(this.type && this.type == "text") $(this).val("");
	   else $(this).attr("checked", false);
      }   
    );
  }
  else {
    var realInput = $(setValueLink).parents("td").find("input").get(0);
	if(realInput && realInput.type && realInput.type != "text") dispatchInputClick(realInput);    
  }
	updateMax(list, item.questionId);
	updateMax(ui.sender, item.questionId);
}
function updateMax(list, questionId) {
  var itemsLength = $(list).find("li.draggableGridItem").length;
  if(list.maxItems != -1 && itemsLength >= list.maxItems) {
	$(list).removeClass("dropList" + questionId).addClass("maxItems");
  }
  else $(list).addClass("dropList" + questionId).removeClass("maxItems");	
}

function itemReorder(event, ui) {
  var prio = 1;
  $(this).find("li.draggableGridItem").each(function() {
      var name = "Q"+this.questionId+"."+this.rowId;
      var input = $("input[type='text'][name^='"+name+"']").get()[0];
	  var list = $(this).parents('ul.ui-sortable').get(0);
      if(input && list.answerId && list.answerId != 0) {
		input.value=prio;
		prio++;
	  }
	  else input.value = "";
  });
}

function dragSortStart(event, ui) {
  var item = $(ui.item).get(0);
  $(item).addClass("answerHover");
}

function dragSortEnd (event, ui) {
  var item = $(ui.item).get(0);
  removeHoverClasses(item);
}

function dragOverList() {
  var list = returnActualList(this);
  $(list).addClass("dragOverList");
}

function dragOutList () {
  var list = returnActualList(this);
  $(list).removeClass("dragOverList");
}

function returnActualList(list) {
  var parent = $(list).parents('.answerAlternativeBox:first');
  if($(parent).length > 0) list = parent;
  return list;
}

function addDragHoverClasses(object) {
  $(object).hover(
    function () {
      $(this).addClass("answerHover");
    },
    function () {
      $(this).removeClass("answerHover");
    }
  );
}

function removeHoverClasses(object) {
  $(object).removeClass("answerHover");
  $(object).unbind('mouseenter mouseleave'); //Unbind hover
  $(object).effect('highlight', {}, 750);
  $(object).mouseleave(function() { addDragHoverClasses(this); });
}

DragDropGrid.prototype.setQuestionId = function(input) {
    var name = input.name ? input.name : "";
    this.questionId = name.charstring("Q", ".");
}

DragDropGrid.prototype.setAnswerAlternatives = function(answerTextCells, answerInputs) {
  if(answerTextCells.length == answerInputs.length || this.singleSort) {
    for(var i=0; i<answerTextCells.length; i++) {
      if(!answerInputs[i].type || answerInputs[i].type != "text") {
        var name = answerInputs[i].name ? answerInputs[i].name : "";
        var id = name.charstring(":");
        if(!id) id = Number(i)+1;
        answerTextCells[i].initialGridItems = new Array();
        answerTextCells[i].answerId = id;
        this.answerAlternatives['A'+id] = answerTextCells[i];
      }
	  else if(this.singleSort) {
        var name = answerTextCells[i].name ? answerTextCells[i].name : "";
        var id = name.charstring(":");
        if(!id) id = Number(i)+1;
        answerTextCells[i].initialGridItems = new Array();
        answerTextCells[i].answerId = id;
        this.answerAlternatives['A'+id] = answerTextCells[i];		
	  }
    }
  }
  else alert("Drag n drop cannot be generated.");
}

DragDropGrid.prototype.setGridItems = function(rowTextCells, rowInputs) {
  if(rowTextCells.length == rowInputs.length) {
    for(var i=0; i<rowTextCells.length; i++) {
      var name = rowInputs[i].name ? rowInputs[i].name : "";
      var id=name.charstring(".", ":");
      if(!id) id = Number(i)+1;
      rowTextCells[i].rowId = id;
      rowTextCells[i].questionId = this.questionId;
      rowTextCells[i].origOrder = rowInputs[i].type == "text" ? rowInputs[i].value : 0;
      this.gridItems['R'+id] = rowTextCells[i];
    }
    this.gridItems = sortObject(this.gridItems, sortByOrigOrder);
    this.gridItemsToInsert = this.gridItems;
  }
  else alert("Drag n drop cannot be generated.");
}
DragDropGrid.prototype.setInitialAnswers = function(checkedInputs) {
    for(var i=0; i<checkedInputs.length; i++) {
      var name = checkedInputs[i].name ? checkedInputs[i].name : "";   
      var rid = name.charstring(".", ":");
      var aid = name.charstring(":");
      this.answerAlternatives['A'+aid].initialGridItems.push('R'+rid);
    }
}

String.prototype.charstring = function(a,b) {
  var charString = null;
  var ai = this.indexOf(a);
  var bi = typeof b != 'undefined ' ? this.indexOf(b) : -1;
  if(ai != -1 && bi != -1) charString = this.substring(+ai+1, bi);
  else if(ai != -1) charString = this.substring(+ai+1);
  return charString;
}

function answerAlternative(a, cell) {
  this.answerId = a;
  this.cellReference = cell;
}

function gridItem(r, cell) {
  this.rowId = r;
  this.cellReference = cell;
}

function sortByOrigOrder(a,b) {
  return a.origOrder - b.origOrder;
}

function sortObject(object, sortFunction){
	var sortedArray = new Array();
	var sortedObj = {};

	for (var i in object){
	  object[i].associativeKey = i;
		sortedArray.push(object[i]);
	}
	sortedArray.sort(sortFunction);

	for (var i in sortedArray){
		sortedObj[sortedArray[i].associativeKey] = sortedArray[i];
	}
	return sortedObj;
}

function dispatchInputClick(elm) { 
	//return;
	var evt = null; 
	if(document.createEvent) { 
		evt = document.createEvent('MouseEvents'); 
		if(elm && elm.dispatchEvent && evt && evt.initMouseEvent) { 
			evt.initMouseEvent( 
			'click', 
			true,     // Click events bubble 
			true,     // and they can be cancelled 
			document.defaultView,  // Use the default view 
			1,        // Just a single click 
			0,        // Don't bother with co-ordinates 
			0, 
			0, 
			0, 
			false,    // Don't apply any key modifiers 
			false, 
			false, 
			false, 
			0,        // 0 - left, 1 - middle, 2 - right 
			null);    // Click events don't have any targets other than 
			            // the recipient of the click 
			elm.dispatchEvent(evt); 
		} 
	} else if( document.createEventObject ) {
	  elm.checked = !elm.checked;
		elm.fireEvent('onclick');
	}
}
