Removing Multiple Items From An ArrayCollection Using selectedIndices - actionscript-3

I have an ArrayCollection that is the dataProvider for a spark.components.List, which has allowMultipleSelection="true". There is a "Remove Selected Items" button which initiates the removal of all the selected items from the ArrayCollection upon being clicked.
I currently use the following method:
myList.selectedIndices.sort(ascendingSort);
// remove items, counting backwards
for (var i:uint = myList.selectedIndices.length; i > 0; i--) {
myArrayCollection.removeItemAt(myList.selectedIndices[i-1]);
}
where ascendingSort does what you expect ;). It works fine, and I know that it will always work.
However, I did take note that if I neglected the sort altogether, to my surprise the removal still worked. The reason for this turned out to be that, when the removeItemAt is called, the selectedIndices are correspondingly updated.
So my question is: Can one rely upon a removeItemAt call updating the values in the selectedIndices? or might that turn out to be different between runtimes and/or Flex SDK versions?
Obviously, if it is reliable then leaving out the sort would be a significant improvement.

Can one rely upon a removeItemAt call updating the values in the
selectedIndices?
Apparently in your use case, yes.
or might that turn out to be different between runtimes and/or Flex
SDK versions?
It may very well change at some future point, or may have changed before. I know that in my experience with list based classes, sometimes modifying the dataProvider may cause the list to go back into the "no selection" state. Removing a single selectedItem on a list that does not allow multiple selection is a good example of that.
Usually, in the apps I've worked on, I'm not removing items from a list based on the user's selection in a list; instead they are usually removed (or filtered) out based on some criteria in the actual object. And that criteria usually is a Boolean value that relates to a checkbox shown in a DataGrid column.

var indexes:Vector.<Object> = list.selectedItems;
while(indexes.length > 0 )
{
var item:* = indexes.pop();
var remindex:int = list.dataProvider.getItemIndex(item);
if (remindex != -1)
{
list.dataProvider.removeItemAt(remindex);
}
}

Related

Store and retrieve selection elements in Google Apps Script via PropertiesService

The goal is to store the selected text into PropertiesService for later insertion into a Google Doc. Kind of like cut and paste so that the user can collapse and expand elements.
The code is
ui = DocumentApp.getUi();
var selection = DocumentApp.getActiveDocument().getSelection();
ui.alert(JSON.stringify(selection))
The alert contents is
[{}]
I understand that selection returns a Range. So I tried to store individual elements:
if (selection) {
var elements = selection.getRangeElements();
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
ui.alert(JSON.stringify(element.getElement()))
}
}
The alert contents for individual elements is always
[{}]
where there is one {} for every element in the list.
The functions I plan to use to store and retrieve follow:
function save_value(elements) {
PropertiesService.getScriptProperties().setProperty('selection', JSON.stringify(elements));
}
function get_value() {
return JSON.parse(PropertiesService.getScriptProperties().getProperty('selection'));
}
I realize there is a workaround here by storing the element values.
element.getElement().asText().getText();
This comes with downsides.
Code complexity when elements are partially selected. If the selection is partially selecting an element, it creates complexity in the code. The code would have to leverage isPartial(), getStartOffset() and getEndOffsetInclusive().
Code complexity in multiple elements. Instead of one swift store, I have to iterate and chain each store, or have multiple stores, or something else.
Unsure about this one but code complexity in distinct elements. Based on the element, the value method varies. For example, storing an image vs text.
Note, I also realized that not all elements can be inserted, and am experimenting to see if there is a workaround by using elements.

What would cause the difference in filter load speed between Chrome and Firefox?

I have a news aggregator page that has multiple filters. The company filter has a large number of companies. When the + button is clicked in Chrome to expand the list and view the list of companies, it takes 6-8 seconds for the entire list to become visible. In Firefox, the list is visible almost instantaneously. Could someone help me investigate what might be causing the difference in load times across browsers?
You need improve DOM Node Finding Performance:
$newsFilterRow.on('click', '.js-filter-more', function(event) {
var $this = $(this)
var $items = $this.closest($newsFilterRow).find($newsFilterItem).filter(':hidden');
var tmp = $items.splice(0, 56);
$(tmp).addClass(newsFilterItemVisibleClass).css('display', 'inline-block');
if ($items.length === 0) {
$this.remove();
}
});
You are using .find() and .filter()
I suggest change these filters to increase the performance in Chrome.
http://www.steveworkman.com/html5-2/javascript/2011/improving-javascript-xml-node-finding-performance-by-2000/
your $items variable is of zero length in all cases BUT for Company.
var $items = $this.closest($newsFilterRow).find($newsFilterItem);
function animate0() {
var tmp = $items.splice(0, 56);
....
for empty arrays splicing inside empty array is cheap there is no memory reallocation/or anything.. but for your Company case, you are splicing non empty array with every animation frame.. that's causing the sluggishness.
Beside consider caching resources and doing DOM lookups outside of animate.. its just too many DOM manipulations going on inside the animate.
Probably Firefox is capturing array screenshot for animate operations.. but thats just a wild guess, for performance difference.

GAS error, listbox field displays "function addKeyPressHandler() {/* */}" instead of list

I just created this form and my first listbox works well, and notes box works well but second listbox is full of junk, non of which is found in the code?
starting with :
"function addKeyPressHandler() {/* */}"
then on to: mousedown, stylePrimary etc
any clue why?
var LOCATION = ['Select a Location','A Res','B Res','C Res','D Res','MNT','OSB','TWB','VP','VM','SITE DEV']
var ISSUETYPE = ['Select an ISSUE TYPE','Poor Workmanship','Lack of Training','Not Per Plans','Not Per Code','Not Per Spec','Plan Conflict']
Although it's hard to say exactly why without seeing more of your code, the "junk" you describe will show up when you are looping over and displaying properties of an object. You're seeing the functions attached to that object.
So check the code you are using to generate the select options on the problematic listbox, it's probably a typo, or perhaps you've inadvertently re-used a variable name and assigned an object too it, or maybe you have an un-quoted string that matches the name of some object.

How to print a tree using Razor

I'm trying to print a simple HTML tree structure, consisting of ul and li elements. I want to be able to pass the view an IEnumerable<T> where T has some hiearchy information (e.g. parent). Now I want the view to output the Tree control much like ASP.NET's Tree used to work. Is there any way to do this in MVC3 using Razor?
I've so far ended up doing it like this:
#PrintCategoryTree(Model.Where(x => !x.ParentCategoryID.HasValue))
#functions{
public IHtmlString PrintCategoryTree(IEnumerable<Aurora.Models.Category> levelCategories) {
if (levelCategories.Count() == 0) { return new HtmlString(String.Empty); }
System.Text.StringBuilder sb = new System.Text.StringBuilder();
TagBuilder childBuilder = new TagBuilder("li");
foreach(var item in levelCategories.OrderBy(x => x.Name)) {
childBuilder.Attributes.Clear();
childBuilder.Attributes.Add("id", item.CategoryID.ToString("N"))
var sub = PrintCategoryTree(Model.Where(x => x.ParentCategoryID == item.CategoryID));
childBuilder.InnerHtml = item.Name + sub.ToString();
sb.AppendLine(childBuilder.ToString());
}
TagBuilder tagBuilder = new TagBuilder("ul")
{
InnerHtml = sb.ToString()
};
return Html.Raw(tagBuilder.ToString());
}
}
The reason being, this is still in the Razor View. And I can keep my presentation logic in my view. It's not exactly what I'd hoped, but I thought I'd share it with you guys here anyway.
Sure it's possible. :) You can acctually go about this in a few ways.
Use something like jsTree and only output the first level of the tree. When a user expands a node, jsTree issues an AJAX callback to get more, and that's just a matter of loading the nodes underneath whatever they opened. I know that's not exactly what you asked, but I wanted to mention it.
If you can either modify the query or do a bit of pre-processing on the data before passing it to razor, change each item in the IEnumberable so that it also includes it's "level" in the tree (1 for a root node, 2 for it's child, 3 for a child of a child, etc). Outputting it at that point is pretty easy. Create a variable in the view holding the current level. When you go to the next row, check if the new level is the same as the old one. If it's not, either open or close enough <ul> tags that you get to the right one for that element.
If you can't do that either, you'll need to keep track of the nodes as you see them in razor. The reason why is that when you find a child from a node that isn't the last one you saw, you'll need to get that node back to figure out how many </ul> tags you need to add to get to the right level. Off the top of my head you could do that by having the view create a Hashtable with the row's key and level for each row you hit. Then when you hit an element and don't know where to put it, look up its parent in the hashtable (since you'll have already seen the parent assuming these are ordered correctly).
Far as I'm aware there's no "display this blob of stuff as a tree" command, so you need to write some logic to get the number of tags to build the levels correct. But hopefully that will help you get started. :)

Flex 4.5 Spark DataGrid - Detect column clicked in selectionChange handler

I have a spark datagrid with selectionMode="multipleRows".
I have three columns in the datagrid.
I don't want the row selection to happen when the user's click falls on the third column of a row.
The row selection should happen only when one of the first two columns is clicked.
How do I achieve this? There is a selectionChanging event for the datagrid, but the GridSelectionEvent object received in the handler does not seem to provide any information about the column on which the click happened.
Thanks!
I figured this out myself. I am not sure if this is a bug in the spark DataGrid. The following is definitely a hack and not clean.
In the grid_mouseDownHandler function in the DataGrid.as file, there is a line:
const columnIndex:int = isCellSelection ? event.columnIndex : -1;
This line is causing the columnIndex to be set as -1 if the selectionMode of the DataGrid is anything other than GridSelectionMode.SINGLE_CELL or GridSelectionMode.MULTIPLE_CELLS. As I mentioned in the original question, I need my datagrid to have a selectionMode of GridSelectionMode.MULTIPLE_ROWS.
I sub-classed the DataGrid and re-implemented the grid_mouseDownHandler (basically copy-pasted the whole function). I changed only the above line to always assign the columnIndex to event.columnIndex.
(I also had to copy some more functions which were referenced by the grid_mouseDownHandler over to my sub-class because those functions were protected or mx_internal. (toggleSelection, extendSelection, isAnchorSet)
Then, in the selectionChanging event handler, I could just do the following:
if( 2 == event.selectionChange.columnIndex )
{
event.preventDefault();
}
I realize that this is not a clean solution, but it is the best I could think of. Maybe someone can suggest a better solution?