What's the right way to expand filtered nodes in ivh-treeview? - treeview

Per the discussion here, currently the ivh-treeview Angular library does not expand collapsed nodes when the tree is filtered and a leaf node matches the filter.
Would the right way to implement this behavior be to add an ng-change handler to the input element used for the filter text and then query the tree in the containing controller (thus, doing it manually)?
There doesn't appear to be any other mechanism by which to detect if the filter is changed.
BTW, there exists no ivh-treeview tag so I can't really tag this properly. Apologies if I've hijacked someone else's tag. That said it appears to be the tag used for other ivh-treeview related questions.

There's really no way to do this elegantly I'm afraid. The best you can do is expand the entire tree (with expandRecursive) when you detect the filter is non-empty (or past some threshold). By completely expanding the tree you get to "show filtered nodes" by virtue of the fact that everything else is hidden by ivhTreeview. That's the easy part. The hard part is when there's no longer a filter how do you restore the tree to it's previous partially-expanded state.
If I had to do it I'd probably end up walking the tree to grab the expanded state from each node before the recursive expand then restore that state when the filter is removed. This would clobber collapse/expand actions while there was a filter in play... you could handle that too but things start to get hairy very quickly. E.g.:
var isExpanded = ivhTreeviewOpts().expandedAttribute
// When the filter becomes non-empty
ivhTreeviewBfs(myTree, function(node) {
node.savedExpandedState = n[isExpanded]
})
ivhTreeviewMgr.expandRecursive(tree)
// When the filter becomes empty
ivhTreeviewBfs(myTree, function(node) {
node[isexpanded] = node.savedExpandedState
})
Here's a rough demo: http://jsbin.com/jijoma/3/edit?html,js,output
Hope that helps!

Related

What does Camel Splitter actually do with XML Document when splitting with xpath?

I have a document with an order and a number of lines. I need to break the order into lines so I have a camel splitter set to xpath with the order line as it's value. This works fine.
However, what I get going forward is an element for the order line, which is what I want, but when converting it I need information from the order element - but if I try to get the parent element via xpath following the split, this doesn't work.
Does Camel create copies of the nodes returned by the xpath expression, or return a list of nodes within the parent document? If the former, can I make it the latter? If the latter, any ideas why a "../*" expression would return nothing?
Thanks!
Screwtape.
Look at the split options that are available when using a Tokenizer:
http://camel.apache.org/splitter.html
You have four different modes (i, w, u, t) and the 'w' one is keeping the ancestor context. In such case, the parent node (=the thing you apparently need) will be repeated in each sub-message
Default:
<m:order><id>123</id><date>2014-02-25</date></m:order>
'w' mode:
<m:orders>
<m:order><id>123</id><date>2014-02-25</date>...</m:order>
</m:orders>

Execute query lazily in Orient-DB

In current project we need to find cheapest paths in almost fully connected graph which can contain lots of edges per vertex pair.
We developed a plugin containing functions
for special traversal this graph to lower reoccurences of similar paths while TRAVERSE execution. We will refer it as search()
for special effective extraction of desired information from results of such traverses. We will refer it as extract()
for extracting best N records according to target parameter without costly ORDER BY. We will refer it as best()
But resulted query still has unsatisfactory performance on full data.
So we decided to modify search() function so it could watch best edges first and prune paths leading to definitely undesired result by using current state of best() function.
Overall solution is effectively a flexible implementation of Branch and Bound method
Resulting query (omitting extract() step) should look like
SELECT best(path, <limit>) FROM (
TRAVERSE search(<params>) FROM #<starting_point>
WHILE <conditions on intermediate vertixes>
) WHERE <conditions on result elements>
This form is very desired so we could adapt conditions under WHILE and WHERE for our current task. The path field is generated by search() containing all information for best() to proceed.
The trouble is that best() function is executed strictly after search() function, so search() can not prune non-optimal branches according to results already evaluated by best().
So the Question is:
Is there a way to pipeline results from TRAVERSE step to SELECT step in the way that older paths were TRAVERSEd with search() after earlier paths handled by SELECT with best()?
the query execution in this case will be streamed. If you add a
System.out.println()
or you put a breakpoint in your functions you'll see that the invocation sequence will be
search
best
search
best
search
...
You can use a ThreadLocal object http://docs.oracle.com/javase/7/docs/api/java/lang/ThreadLocal.html
to store some context data and share it between the two functions, or you can use the OCommandContext (the last parameter in OSQLFunction.execute() method to store context information.
You can use context.getVariable() and context.setVariable() for this.
The contexts of the two queries (the parent and the inner query) are different, but they should be linked by a parent/child relationship, so you should be able to retrieve them using OCommandContext.getParent()

d3 filter selection not working?

Either I am not using d3's selection.filter correctly, or it is buggy. I can distill the issue to a few lines. I'm in the Chrome debugger with d3 loaded. Let's start with an empty selection
d3.selectAll("nonexistant").empty()
> true
and bind some data to it.
d3.selectAll("nonexistant").data([1,2,3,4])
> [Array[4]]
Good, so it has size four. Let's check with selection.size:
d3.selectAll("nonexistant").data([1,2,3,4]).size()
> 0
Hmm, I guess that's because there are no DOM elements yet the update selection is empty since there were no previous elements. So let's make access the enter selection.
d3.selectAll("nonexistant").data([1,2,3,4]).enter()
> [Array[4]]
d3.selectAll("nonexistant").data([1,2,3,4]).enter().size()
> TypeError: undefined is not a function
d3.selectAll("nonexistant").data([1,2,3,4]).enter().append("p").size()
> 4
Not sure why the enter selection causes an error, (UPDATE: Fixed in v3.4.12) but anyway, if we try filtering using the example function in the docs,
function odds(d, i) { return i & 1; }
d3.selectAll("nonexistant").data([1,2,3,4]).filter(odds);
> [Array[0]]
d3.selectAll("nonexistant").data([1,2,3,4]).enter().filter(odds);
> []
d3.selectAll("nonexistant").data([1,2,3,4]).enter().append("p").filter(odds)
> [Array[2]]
Why is it silently filtering out all elements when there are no DOM elements bound? It does seem to be working when I already have DOM elements. But that feels pretty useless, since I don't want to create elements for data I'm discarding. Maybe if I put the filter earlier?
d3.selectAll("nonexistant").data([1,2,3,4]).filter(odds).enter().append("p").size()
> TypeError: undefined is not a function
d3.selectAll("nonexistant").data([1,2,3,4]).enter().filter(odds).append("p").size()
> TypeError: undefined is not a function
Nope. It seems the way to go is with JS's native filter on arrays:
d3.selectAll("nonexistant").data([1,2,3,4].filter(odds)).enter().append("p").size()
> 2
The d3 docs do not seem to differentiate between selections that have DOM elements bound and those that do not. It seems that I should be able to stick filter anywhere in my method chain (and call size on any selection), and get the correct result without a type error. Granted, filter also supports CSS selectors that will require DOM elements, but I'm not using them here.
What I want to know: There is a mismatch between what d3 is doing and what I expect. To what extent am I harboring misconceptions about selections and what operations are valid on them? To what extent is the documentation unclear? Does any of this behavior qualify as a bug?
From the documentation of the .enter() method:
... the entering selection only defines append, insert, select and call operators; you must use these operators to instantiate the entering nodes before modifying any content. (Enter selections also support empty to check if they are empty.)
Calling anything else doesn't produce useful results. Whether or not that's a bug, a side-effect or a feature is perhaps debatable. In almost all cases, it doesn't create any barriers, except maybe if you need to know this selection's size() to find out how many datums from the array you pass to data() didn't already have elements created.
Once you call append() on the entering selection though, it behaves well, like any normal selection. In fact, append() is returning a new selection, so it !== the return value of enter().
That's when you can also check the size() of this selection, so really it only counts as an issue if you needed to know the size PRIOR to calling append().
You're correct that using the native array filter is the solution IF you don't need to even append elements where odds(d) == false.
Filter is useful when you've already created the DOM nodes (e.g. <p>s) that are bound to [1,2,3,4], and (e.g. in an event handler, when user clicks a "highlight all odds" button ) you call
d3.selectAll('p').filter(odds).css('color', 'red')
BTW, that was a really well written question.

XPATH - cannot select grandparent node

I am trying to parse a live betting XML feed and need to grab each bet from within the code. In plain English I need to use the tag 'EventSelections' for my base query and 'loop' through these tags on the XML so I grab all that data and it creates and entity for each one which I can use on a CMS.
My problem is I want to go up two places in the tree to a grandparent node to gather that info. Each EventID refers to the unique name of a game and some games have more bets than others. It's important that I grab each bet AND the EventID associated with it, problem is, this ID is the grandparent each time. Example:
<Sportsbet Time="2013-08-03T08:38:01.6859354+09:30">
<Competition CompetitionID="18" CompetitionName="Baseball">
<Round RoundID="2549" RoundName="Major League Baseball">
<Event EventID="849849" EventName="Los Angeles Dodgers (H Ryu) At Chicago Cubs (T Wood)" Venue="" EventDate="2013-08-03T05:35:00" Group="MTCH">
<Market Type="Match Betting - BIR" EachWayPlaces="0">
<EventSelections BetSelectionID="75989549" EventSelectionName="Los Angeles Dodgers">
<Bet Odds="1.00" Line=""/>
</EventSelections>
<EventSelections BetSelectionID="75989551" EventSelectionName="Chicago Cubs">
<Bet Odds="17.00" Line=""/>
</EventSelections>
Does anyone know how I can grab the granparent tags as well?
Currently I am using:
//EventSelections (this is the context)
.//#BetSelectionID
.//#EventSelectionName
I have tried dozens of different ways to do this including the ../.. operator which won't work either. I'd be eternally grateful for any help on this. Thanks.
I think you just haven't gone far enough up the tree.
../* is a two-step location bath with abbreviations, expanded to parent::node()/child::* ... so in effect you are going up the tree with the first step, but back down the tree for the second step.
Therefore, ../* gives you your siblings (parent's children), ../../* gives you your aunts and uncles (grandparent's children), and ../../../* gives you your grandparent and its siblings (great-grandparent's children).
For attributes, ../#* is an abbreviation for parent::node()/attribute::* and attributes are attached to elements, they are not considered children. So you are going sideways, not down the tree in the second step.
Therefore, unlike above, ../#* gives you your parent's attributes, while ../../#* gives you your grandparent's attributes.
But using // in your situation is really inappropriate. // is an abbreviation for /descendent-or-self::node()/ which walks all the way down a tree to the leaves of the tree. It should be used only in rare occasions (and I cringe when I see it abused on SO questions).
So ..//..//..//#RoundID may work for you, but it is in effect addressing attributes all over the tree and not just an attribute of your great-grandparent, which is why it is finding the attribute of your grandparent. ../../#RoundID should be all you need to get the attribute of your grandparent.
If you torture a stylesheet long enough, it will eventually work for you, but it really is more robust and likely faster executing to address things properly.
You could go with ancestor::Event/#EventID, which does exactly you asked for: matches an ancestor element named Event and returns it's EventID attribute.

xpath - matching value of child in current node with value of element in parent

Edit: I think I found the answer but I'll leave the open for a bit to see if someone has a correction/improvement.
I'm using xpath in Talend's etl tool. I have xml like this:
<root>
<employee>
<benefits>
<benefit>
<benefitname>CDE</benefitname>
<benefit_start>2/3/2004</benefit_start>
</benefit>
<benefit>
<benefitname>ABC</benefitname>
<benefit_start>1/1/2001</benefit_start>
</benefit>
</benefits>
<dependent>
<benefits>
<benefit>
<benefitname>ABC</benefitname>
</benefit>
</dependent>
When parsing benefits for dependents, I want to get elements present in the employee's
benefit element. So in the example above, I want to get 1/1/2001 for the dependent's
start date. I want 1/1/2001, not 2/3/2004, because the dependent's benefit has benefitname ABC, matching the employee's benefit with the same benefitname.
What xpath, relative to /root/employee/dependent/benefits/benefit, will yield the value of
benefit_start for the benefit under parent employee that has the same benefit name as the
dependent benefit name? (Note I don't know ahead of time what the literal value will be, I can't just look for 'ABC', I have to match whatever value is in the dependent's benefitname element.
I'm trying:
../../../benefits/benefit[benefitname=??what??]/benefit_start
I don't know how to refer to the current node's ancestor in the middle of
the xpath (since I think "." at the point I have ??what?? will refer to
the benefit node of the employee/benefits.
EDIT: I think what I want is "current()/benefitname" where the ??what?? is. Seems to work with saxon, I haven't tried it in the etl tool yet.
Your XML is malformed, and I don't think you've described your siduation very well (the XPath you're trying has a bunch of ../../s at the beginning, but you haven't said what the context node is, whether you're iterating through certain nodes, or what.
Supposing the current context node were an employee element, you could select benefit_starts that match dependent benefits with
benefits/benefit[benefitname = ../../dependent/benefits/benefit/benefitname]
/benefit_start
If the current context node is a benefit element in a dependents section, and you want to get the corresponding benefit_start for just the current benefit element, you can do:
../../../benefits/benefit[benefitname = current()/benefitname]/benefit_start
Which is what I think you've already discovered.

Resources