суббота, 25 декабря 2010 г.

К слову, о спринге

С AJAX в том виде как оно есть я не работал, и думал, что все окажется куда страшнее. На самом деле все просто как никогда. Создал контроллер, замапил, и вуаля!


package org.springframework.samples.mvc.ajax.tree;

import org.springframework.samples.mvc.ajax.tree.tree.DataLoader;
import org.springframework.samples.mvc.ajax.tree.tree.IDataLoader;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import static org.springframework.samples.mvc.ajax.tree.utils.Constants.NESTING_LEVEL;

/**
* @author Vyacheslav Kovalyov
* @version 1.0
*/

@Controller
public class AjaxTreeController {

public AjaxTreeController() {
this.dao= new TreeXMLDao();
}

@RequestMapping(value = "getChildren", method = RequestMethod.GET)
public
@ResponseBody
Object getChildren(@RequestParam String parentNodeId) {

return dao.getSubTree(parentNodeId, NESTING_LEVEL).asJSON();
}

private final ITreeXMLDao dao;
}



И вытаскиваем значение со страницы


$.ajax({
url:controllerName,
data:{parentNodeId: nodeId},
dataType: 'json',
success: function(data) {
//actions
}
});

пятница, 24 декабря 2010 г.

Лес

В дебрях интернета была найдена библиотечка для рисования деревьев и графов (а также других приблуд) на JS - JIT (http://thejit.org). JavaScript я не знаю, попробовал, не понравилось. Совсем.
Мне понадобилось данное дерево использовать с большим количеством нодов. При этом, подгружая нужные ноды через AJAX, и удаляя из HTML collapsed ноды.
Если подгрузка нодов - занятие тривиальное - достаточно написать метод request (в данном случае я использую библиотеку jQuery, а на серверной части сидит обычный Spring 3):


request: function(nodeId, level, onComplete) {

$.ajax({
url:controllerName,
data:{parentNodeId: nodeId},
dataType: 'json',
success: function(data) {
$jit.json.prune(data, level);
if (level == 0) addNodeOnTree(data, nodeId);
onComplete.onComplete(nodeId, data);
}
});
}

function addNodeOnTree(node, parentId) {

node.id = parentId;
st.addSubtree(node, 'animate', {
hideLabels: false,
onAfterCompute: function() {
st.compute();
}
});
}



А вот с удалением нодов - дела обстоят не так радужно. Конечно, есть метод removeSubtree, который удаляет поддерево, есть метод removeNode. Но с этим связано несколько проблем:
removeSubtree жует чрезмерно много ресурсов;
remobeNode удаляет только нод из нашего графа, но не удаляет из html. и работает как то не особо красиво.
Стоит обратить внимание на метод hide, в описании которого ясно сказано, что хрен нам, а не удаление:


hide: function(nodes, controller) {
var viz = this.viz;
for(var i=0; i<nodes.length; i++) {
// TODO nodes are requested on demand, but not
// deleted when hidden. Would that be a good feature?
// Currently that feature is buggy, so I'll turn it off
// Actually this feature is buggy because trimming should take
// place onAfterCompute and not right after collapsing nodes.
if (true || !controller || !controller.request) {
///////


*для шибко умных хочу добавить, что это true - не индийский код, а "посмотрите на реализацию, можете поменять, но это дело забаговано, все на свой страх и риск"

Помучившись с этим какое то время, я решил, что хай же с ним, и просто сделаем по клику на нод фильтр, который будет удалять скрытые ноды из графа, и их же из html. все довольно просто. Но все равно, мне это не очень нравится.


function onNodeClick(id) {
for (var i in st.graph.nodes) {

if (i != undefined && !st.graph.getNode(i).drawn) {

st.graph.removeNode(i);

var div = document.getElementById(i);
if (div != null)
div.parentNode.removeChild(div)
}
}
}



суть проста: чтобы не удалить по неосторожности другие элементы страницы, мы отсеиваем только скрытые (не html display none, а которые collapsed в дереве) !st.graph.getNode(i).drawn ноды, удаляем их из дерева
st.graph.removeNode(i);
и из html
div.parentNode.removeChild(div).

Стоит обратить внимание на то, что если дерево вылазит за границы экрана, то в html эти ноды показываются как display none, а дерево их видит как st.graph.getNode(i).drawn == true

Вот такие первые впечатления. Само дерево настраивается под ваши нужды, достаточно открыть документацию.