/* spree YUI support stuffs */
spree.YUI = {
registered_trees: {},
inplace_editors: [],
drag_objects: [],
drop_objects: [],
goingUp: false,
lastY:0,
drag_parent:null,
drag_node:null,
drag_text:null,
new_node: function() {
var target = spree.YUI.current_tree.current_target;
var tree = spree.YUI.current_tree;
var rand_no = Math.ceil(1000000 * Math.random());
var node_config = {id: 'new_taxon_node_' + rand_no, html:'New Taxon', parent_id: target.data.id}
var HTMLnode = spree.YUI.initialize_node(tree, node_config);
//refresh the tree and reattach all inplace editors
if(target.expanded) {
target.collapse();
target.expand();
} else {
target.expand();
}
target.refresh();
spree.YUI.register_inplace_controls();
var target_url = target.data.object_url.split('/');
var parent_id = target_url.last();
target_url = target_url.slice(0, (target_url.length - 1))
//add inplace creator
var ipe = new Ajax.InPlaceEditor('new_taxon_node_' + rand_no, target_url.join('/'), {
callback: function(form, value) { return 'taxon[name]=' + encodeURIComponent(value) + '&taxon[parent_id]=' + encodeURIComponent(parent_id)},
onComplete: function(transport, element) {
if (transport){
//got response from server
var new_taxon = transport.responseText.evalJSON().taxon;
var tree = spree.YUI.current_tree;
//destory inplace creator
spree.YUI.remove_inplace_control(element.id);
var node = tree.tree_view.getNodeByProperty('id', element.id);
node.data.id = new_taxon.id;
node.data.object_url = this.url + '/' + new_taxon.id;
node.data.position = new_taxon.position;
node.html = '' + new_taxon.name + '
';
//refresh the tree and reattach all inplace editors
node.parent.refresh();
spree.YUI.register_inplace_controls();
//add inplace editor & drag / drop
spree.YUI.inplace_editors[spree.YUI.inplace_editors.length] = new Ajax.InPlaceEditor('node_' + new_taxon.id, node.data.object_url, {
callback: function(form, value) { return 'taxon[name]=' + encodeURIComponent(value) },
onComplete: spree.YUI.after_inplace_edit,
savingText: 'Saving... ',
textBetweenControls: ' or ',
ajaxOptions: {method: 'put'}
});
var ddp = new YAHOO.util.DDProxy('node_' + new_taxon.id);
ddp = spree.YUI.register_drag_events(ddp);
spree.YUI.drag_objects[spree.YUI.drag_objects.length] = ddp;
spree.YUI.drop_objects[spree.YUI.drop_objects.length] = new YAHOO.util.DDTarget('node_' + new_taxon.id);
}else{
//no response from server (user clicked cancel)
}
},
savingText: 'Adding... ',
textBetweenControls: ' or ',
ajaxOptions: {method: 'post'}});
spree.YUI.inplace_editors[spree.YUI.inplace_editors.length] = ipe;
//get the newly created node, and force the onclick event, to display the inplace creator
spree.YUI.fire_event($('new_taxon_node_' + rand_no), 'click');
var form = $('new_taxon_node_' + rand_no + '-inplaceeditor');
var cancel_link = form.select('.editor_cancel_link')[0];
//delete node again if user cancels before saving.
cancel_link.observe('click', function(event){
var parent = HTMLnode.parent
tree.tree_view.removeNode(HTMLnode, true)
spree.YUI.remove_inplace_control(HTMLnode.data.id)
if(parent.children.length==0) parent.collapse();
parent.refresh();
spree.YUI.register_inplace_controls();
});
},
edit_node: function() {
var target = spree.YUI.current_tree.current_target;
var span = $('node_' + target.data.id);
spree.YUI.fire_event(span, 'click');
},
delete_node: function() {
var tree = spree.YUI.current_tree;
var target = spree.YUI.current_tree.current_target;
var url = target.data.object_url;
if (confirm('Are you sure that you want to delete this taxon?')){
new Ajax.Request(url, {
method: 'post',
parameters: {_method: 'delete'},
onSuccess: function(transport){
var parent = target.parent
//remove node
tree.tree_view.removeNode(target, true)
//destory inplace editor
spree.YUI.remove_inplace_control('node_' + target.data.id)
//refresh the tree and reattach all inplace editors
if(parent.children.length==0) parent.collapse();
parent.refresh();
spree.YUI.register_inplace_controls();
},
onLoading: function(){
Element.show('taxon_' + target.data.id)
}
});
}
},
move_node_up: function() {
var tree = spree.YUI.current_tree;
var target = spree.YUI.current_tree.current_target;
var url = target.data.object_url;
new Ajax.Request(url, {
method: 'post',
parameters: '_method=put&taxon[position]=' + (target.data.position - 1),
onLoading: function(){
Element.show('taxon_' + target.data.id)
},
onSuccess: function(transport){
Element.hide('taxon_' + target.data.id)
target.data.position = (target.data.position - 1);
var parent = target.parent;
tree.tree_view.popNode(target);
parent.children.each(function(node) {
if(node.data.position==target.data.position){
node.data.position = (target.data.position + 1);
target.insertBefore(node);
node.parent.refresh();
spree.YUI.register_inplace_controls();
throw $break;
}
});
}
});
},
move_node_down: function() {
var tree = spree.YUI.current_tree;
var target = spree.YUI.current_tree.current_target;
var url = target.data.object_url;
new Ajax.Request(url, {
method: 'post',
parameters: '_method=put&taxon[position]=' + (target.data.position + 1),
onLoading: function(){
Element.show('taxon_' + target.data.id)
},
onSuccess: function(transport){
Element.hide('taxon_' + target.data.id)
target.data.position = (target.data.position + 1);
var parent = target.parent;
tree.tree_view.popNode(target);
parent.children.each(function(node) {
if(node.data.position==target.data.position){
node.data.position = (target.data.position - 1);
target.insertAfter(node);
node.parent.refresh();
spree.YUI.register_inplace_controls();
throw $break;
}
});
}
});
},
cut_node: function() {
var tree = spree.YUI.current_tree;
var target = spree.YUI.current_tree.current_target;
spree.YUI.drag_node = target;
spree.YUI.drag_parent = target.parent;
if (tree.tree_view.getNodeByProperty('id', target.data.id)) tree.tree_view.popNode(target);
if (spree.YUI.drag_parent.children.length==0) spree.YUI.drag_parent.collapse();
tree.tree_view.root.refresh();
spree.YUI.register_inplace_controls();
},
paste_node: function() {
var tree = spree.YUI.current_tree;
var target = spree.YUI.current_tree.current_target;
var count = target.children.length
var paste_node = spree.YUI.drag_node;
paste_node.appendTo(target);
if (!target.expanded) target.expand();
tree.tree_view.root.refresh();
spree.YUI.register_inplace_controls();
var url = paste_node.data.object_url;
if(target.data.id==spree.YUI.drag_parent.data.parent_id){
//being pasted onto same parent
}
console.log(count)
new Ajax.Request(url, {
method: 'post',
parameters: '_method=put&taxon[parent_id]=' + encodeURIComponent(target.data.id) + '&taxon[position]=' + count,
onLoading: function(){
Element.show('taxon_' + paste_node.data.id)
},
onSuccess: function(transport){
Element.hide('taxon_' + paste_node.data.id)
paste_node.data.parent_id = target.data.id;
paste_node.data.position = count ;
}
});
spree.YUI.drag_node = null;
spree.YUI.drag_parent = null;
},
fire_event: function(obj, event){
if (document.createEventObject){
// dispatch for IE
var evt = document.createEventObject();
return obj.fireEvent('on'+event,evt)
}
else{
// dispatch for firefox + others
var evt = document.createEvent("HTMLEvents");
evt.initEvent(event, true, true ); // event type,bubbling,cancelable
obj.dispatchEvent(evt);
}
},
onTriggerContextMenu: function(p_sType, p_Args) {
var event = p_Args[0];
var node = YAHOO.util.Event.getTarget(event);
// find the target which is a tree node
var target = YAHOO.util.Dom.hasClass(node, 'ygtvhtml')
? node
: YAHOO.util.Dom.getAncestorByClassName(node, 'ygtvhtml');
if (target) {
var tree = spree.YUI.set_current_target(target);
this.clearContent();
var items = {};
if (spree.YUI.current_tree.current_target == tree.root) {
items = [{ text: "New Child", onclick: { fn: spree.YUI.new_node } } ]
} else {
items = [
{ text: "New Child", onclick: { fn: spree.YUI.new_node } },
{ text: "Edit", onclick: { fn: spree.YUI.edit_node } },
{ text: "Delete", onclick: { fn: spree.YUI.delete_node } },
{ text: "Cut", onclick: { fn: spree.YUI.cut_node } }];
}
if(spree.YUI.drag_node){
items[items.length] = { text: "Paste", onclick: { fn: spree.YUI.paste_node } }
}
var node_id = node.id.gsub('node_', '');
node = tree.tree_view.getNodeByProperty('id',node_id);
if(Object.isUndefined(node)){
//inplace editing, drop submenu
items = {};
}else{
if(node.previousSibling!=null){
items[items.length] = { text: "Move Up", onclick: { fn: spree.YUI.move_node_up } }
}
if(node.nextSibling!=null){
items[items.length] = { text: "Move Down", onclick: { fn: spree.YUI.move_node_down } }
}
}
this.itemData = items;
this.init();
}
},
build_tree: function(container_element_id, tree_data) {
var tree = spree.YUI.registered_trees[container_element_id];
if (tree) {
spree.YUI.destroy_tree(tree);
}
tree = {};
spree.YUI.register_tree(tree, container_element_id, "taxonomy_tree");
tree.tree_view = new YAHOO.widget.TreeView(container_element_id);
for (var i = 0; i < tree_data.length; i++) {
spree.YUI.initialize_node(tree, tree_data[i]);
}
// This hack does not make me happy
var rand_no = Math.ceil(1000000 * Math.random());
tree.context_menu = new YAHOO.widget.ContextMenu("cm_" + container_element_id + '_' + rand_no,
{ trigger: container_element_id,
lazyload: true,
itemdata: {} });
tree.context_menu.subscribe("triggerContextMenu", spree.YUI.onTriggerContextMenu );
return tree;
},
add_inplace_controls: function(tree_data){
//add drop control for root node
spree.YUI.drop_objects[spree.YUI.drop_objects.length] = new YAHOO.util.DDTarget('node_' + tree_data[0].id);
//add inplace editor and drag/drop controls
for (var i = 1; i < tree_data.length; i++) {
spree.YUI.inplace_editors[spree.YUI.inplace_editors.length] = new Ajax.InPlaceEditor('node_' + tree_data[i].id, tree_data[i].object_url, {
callback: function(form, value) { return 'taxon[name]=' + encodeURIComponent(value) },
onComplete: spree.YUI.after_inplace_edit,
textBetweenControls: ' or ',
savingText: 'Saving... ',
ajaxOptions: {method: 'put'}
});
var ddp = spree.YUI.register_drag_events(new YAHOO.util.DDProxy('node_' + tree_data[i].id));
spree.YUI.drag_objects[spree.YUI.drag_objects.length] = ddp;
spree.YUI.drop_objects[spree.YUI.drop_objects.length] = new YAHOO.util.DDTarget('node_' + tree_data[i].id);
}
},
register_inplace_controls: function(){
spree.YUI.inplace_editors.each(function(ipe) {
var element = $(ipe.element.id);
if (element!=null) ipe.initialize(element, ipe.url, ipe.options);
});
spree.YUI.drag_objects = spree.YUI.drag_objects.collect(function(ddp, i) {
return spree.YUI.register_drag_events( new YAHOO.util.DDProxy(ddp.id));
});
spree.YUI.drop_objects = spree.YUI.drop_objects.each(function(dd, i) {
return new YAHOO.util.DDTarget(dd.id);
});
},
register_drag_events: function(ddp){
ddp.onDragDrop = spree.YUI.onDragDrop;
ddp.startDrag = spree.YUI.startDrag;
ddp.onDragOut = spree.YUI.onDragOut;
ddp.onDragOver = spree.YUI.onDragOver;
ddp.endDrag = spree.YUI.endDrag;
ddp.onDrag = spree.YUI.onDrag;
ddp.onInvalidDrop = spree.YUI.onInvalidDrop;
return ddp;
},
remove_inplace_control: function(element_id){
var ipe = spree.YUI.inplace_editors.find(function(n) { return n.element.id == element_id })
ipe.destroy();
spree.YUI.inplace_editors.splice(spree.YUI.inplace_editors.indexOf(ipe), 1);
},
after_inplace_edit: function(transport, element) {
if (transport){
//got response from server
var tree = spree.YUI.find_tree_by_element(element);
var node = tree.tree_view.getNodeByProperty('id', element.id.gsub('node_', ''));
node.html = '' + transport.responseText + '
';
}
},
initialize_node: function(tree, node) {
var parent_node = node.parent_id == null
? tree.tree_view.getRoot()
: tree.tree_view.getNodeByProperty('id', node.parent_id);
var HTMLnode = new YAHOO.widget.HTMLNode(node, parent_node, false, true);
HTMLnode.renderHidden=true;
if (node.parent_id == null){
tree.root = tree.tree_view.getNodeByProperty('id', node.id);
if(!tree.root.expanded) tree.root.expand();
}
return HTMLnode;
},
set_current_target: function(target) {
var tree = spree.YUI.find_tree_by_element(target);
tree.current_target = null;
var spree_target = YAHOO.util.Dom.getElementsByClassName('spree-YUI-tree-node','span',target)
var target_id = spree_target[0].id;
if(target_id.include('new_taxon_node_')){
tree.current_target = tree.tree_view.getNodeByProperty('id', target_id);
}else{
tree.current_target = tree.tree_view.getNodeByProperty('id',target_id.gsub('node_', ''));
}
spree.YUI.current_tree = tree;
return tree;
},
reset_current_target: function(target) {
spree.YUI.current_tree = null;
},
find_tree_by_element: function(el) {
var container = YAHOO.util.Dom.getAncestorByClassName(el, 'spree-YUI-tree-container');
var tree = spree.YUI.registered_trees[container.id];
return tree;
},
register_tree: function(tree, id, type) {
var container = YAHOO.util.Dom.get(id);
tree.id = id;
YAHOO.util.Dom.addClass(id, 'spree-YUI-tree-container');
spree.YUI.registered_trees[id] = tree;
// spree.YUI.registered_trees[type] = new Array();
// spree.YUI.registered_trees[type].push(tree);
},
destroy_tree: function(tree) {
// unsubscribe menu
tree.context_menu.unsubscribe("triggerContextMenu", spree.YUI.onTriggerContextMenu);
delete tree.context_menu;
// unregister tree
delete spree.YUI.registered_trees[tree.id];
// destroy tree view
delete tree.tree_view;
},
onload: function() {
},
onDragDrop: function(e, id) {
if(!spree.YUI.drag_node) return
var dragged_node = spree.YUI.drag_node;
var tree = dragged_node.tree;
var temp_node = tree.getNodeByProperty('id', 'temp_node');
var data = dragged_node.data;
var n = $('node_' + dragged_node.data.id);
n.style.color='#000';
n.style.backgroundColor='#fff'
dragged_node.setHtml(n.up().innerHTML);
dragged_node.data = data;
var old_parent = dragged_node.data.parent_id;
//remove from previous location
if (tree.getNodeByProperty('id', dragged_node.data.id)) tree.popNode(dragged_node);
if (spree.YUI.drag_parent.children.length==0) spree.YUI.drag_parent.collapse();
//render node in correct location
dragged_node.data.parent_id = temp_node.parent.data.id;
dragged_node.insertBefore(temp_node);
tree.removeNode(temp_node);
tree.root.refresh();
//get position of node
var position = 0;
//get actual position of dropped node
dragged_node.parent.children.each(function(node) {
if(node.data.id != dragged_node.data.id){
position = position + 1;
}else{
throw $break;
}
});
//reset all nodes to correct values
var i = 0;
dragged_node.parent.children.each(function(node) {
node.data.position = i;
i = i + 1;
});
var url = dragged_node.data.object_url;
var params = '_method=put&taxon[position]=' + position;
if(old_parent != dragged_node.data.parent_id){
params = params + '&taxon[parent_id]=' + encodeURIComponent(dragged_node.parent.data.id)
}
new Ajax.Request(url, {
method: 'post',
parameters: params,
onLoading: function(){
Element.show('taxon_' + dragged_node.data.id)
},
onSuccess: function(transport){
Element.hide('taxon_' + dragged_node.data.id)
dragged_node.data.parent_id = drop_node.data.id;
dragged_node.data.position = position;
if(old_parent.children.length==0) old_parent.collapse();
}
});
spree.YUI.register_inplace_controls();
spree.YUI.drag_node = null;
spree.YUI.drag_parent = null;
},
startDrag: function(x, y) {
var dragEl = this.getDragEl();
var clickEl = this.getEl();
if(!clickEl) return
var tree = spree.YUI.find_tree_by_element(clickEl);
spree.YUI.current_tree = tree;
target = tree.tree_view.getNodeByProperty('id', clickEl.id.gsub('node_', ''));
spree.YUI.drag_node = target;
spree.YUI.drag_text = clickEl.textContent;
spree.YUI.drag_parent = target.parent;
var data = target.data;
var n = $('node_' + target.data.id);
n.style.color='#ccc';
n.style.backgroundColor='#fff'
target.setHtml(n.up().innerHTML);
target.data = data;
dragEl.innerHTML = ' ';
dragEl.style.border = 'none';
var ddp = spree.YUI.register_drag_events(new YAHOO.util.DDProxy(dragEl));
},
onDragOut: function(e, id){
var tree = spree.YUI.drag_node.tree;
spree.YUI.drop_temp_node(tree);
tree.root.refresh();
spree.YUI.register_inplace_controls();
},
onDragOver: function(e, id) {
if(id=='temp_node') return
if(!id.include('node')) return
var el;
if ("string" == typeof id) {
el = YAHOO.util.DDM.getElement(id);
} else {
el = YAHOO.util.DDM.getBestMatch(id).getEl();
}
if(!el) return
var tree = spree.YUI.find_tree_by_element(el);
spree.YUI.current_tree = tree;
var hover_node = tree.tree_view.getNodeByProperty('id', el.id.gsub('node_', ''));
var node_config = {id: 'temp_node', html:'' + spree.YUI.drag_text + ''}
temp_node = new YAHOO.widget.HTMLNode(node_config, null, false, true);
if (spree.YUI.goingUp) {
spree.YUI.drop_temp_node(tree.tree_view);
if(hover_node.index==1){
//hovering over root, can only insert as child
if(hover_node.children.length>0){
temp_node.insertBefore(hover_node.children[0]);
}else{
temp_node.appendTo(hover_node);
}
} else {
temp_node.insertBefore(hover_node);
}
}else{
if(hover_node.children.length>0){
spree.YUI.drop_temp_node(tree.tree_view);
if(hover_node.expanded){
temp_node.insertBefore(hover_node.children[0]);
} else {
temp_node.insertAfter(hover_node);
}
}else{
spree.YUI.drop_temp_node(tree.tree_view);
temp_node.insertAfter(hover_node);
}
}
tree.tree_view.root.refresh();
spree.YUI.register_inplace_controls();
},
onDrag: function(e) {
// Keep track of the direction of the drag for use during onDragOver
var y = YAHOO.util.Event.getPageY(e);
if (y < spree.YUI.lastY) {
spree.YUI.goingUp = true;
} else if (y > spree.YUI.lastY) {
spree.YUI.goingUp = false;
}
spree.YUI.lastY = y;
},
endDrag: function(e) {
// override so source object doesn't move when we are done
},
onInvalidDrop: function(e) {
var dragged_node = spree.YUI.drag_node;
var data = dragged_node.data;
var n = $('node_' + dragged_node.data.id);
n.style.color='#000';
n.style.backgroundColor='#fff'
dragged_node.setHtml(n.up().innerHTML);
dragged_node.data = data;
var tree = spree.YUI.current_tree;
spree.YUI.drop_temp_node(tree.tree_view);
tree.tree_view.root.refresh();
spree.YUI.register_inplace_controls();
spree.YUI.drag_node = null;
spree.YUI.drag_parent = null;
},
drop_temp_node: function(tree) {
var rm = tree.getNodeByProperty('id', 'temp_node');
if(rm) tree.removeNode(rm, false);
}
}; // end spree.YUI namespace