-
-
Save leepfrog/4498789 to your computer and use it in GitHub Desktop.
| Ember.ArrayPipelinePlugin = Ember.Object.extend | |
| # | |
| # Public | |
| # | |
| # Define a set of properties you would like to observe on the array for | |
| # reprocessing. | |
| # | |
| # If another plugin earlier in the pipeline observes the same property, | |
| # then this plugin will wait to process until the other plugin in the pipeline | |
| # triggers the process action | |
| # | |
| # If this plugin is the first to observe a specific type of property, then | |
| # we will setup observers on our results array to watch for those properties | |
| # if this changes, we should probably tell the pipeline that our properties changed | |
| # so that it can recalculate who is responsible for future observations | |
| observeProperties: [] | |
| # This is typically overriden to perform the function given on the input array | |
| # In: filtered array from earlier pipeline processes (or full element if this is the) | |
| # first plugin | |
| # Out: A processed array | |
| process: (array) -> return array | |
| # | |
| # Private | |
| # | |
| # This is our results array. We hold on to the results from our last | |
| # operation so that we can add / remove observers as needed for processing | |
| _results: [] | |
| # This is a property that should be set by the Pipeline (or should be a bound property | |
| # from the pipeline) | |
| # | |
| # Mutations to this array should be done through an add/remove observer method so that | |
| # we can properly teardown observers on objects in our _results array | |
| _observeProperties: [] | |
| # The pipeline that we are connected to | |
| # This is used to call back after we have finished processing and for obtaining our | |
| # initial observe properties | |
| _pipeline: null | |
| # This is our entry point to processing for our array | |
| # in here, we should do a few things | |
| # 1) send the array for processing | |
| # 2) find the add / remove differences | |
| # 3) teardown observers on objects in our results array that are being removed | |
| # 4) setup observers on objects that are being appended to our results array | |
| # 5) reset results array | |
| # | |
| # Input: an array used for processing | |
| # Output: none | |
| _in: (array) -> | |
| # process | |
| # find add diff / remove diff | |
| # teardown observers on removed objects | |
| # setup observers on add objects | |
| # set results for future processing | |
| # Triggers the pluginResult method on the pipeline so that the _results array can either | |
| # be processed by the next plugin or set as the new arranged content | |
| # Input: nothing | |
| # Output: Nothing | |
| _out: -> @_pipeline.pluginResult(@_results) | |
| # Input: an array of objects to remove observers on -- this would be used if objects | |
| # are being removed from the array | |
| # Output: none | |
| _teardownObservers:(array) -> | |
| # Input: an array of objects to add observers on -- this would be used if objects | |
| # are being added to the array | |
| # Output: none | |
| _setupObservers:(array)-> | |
| # Example filter plugin | |
| App.FilterPlugin = Ember.ArrayPipelinePlugin.extend | |
| observeProperties: ['name', 'isStarred'] | |
| process: (array) -> | |
| # Write filtering function here | |
| # Return result array | |
| # Example sort plugin | |
| App.SortPlugin = Ember.ArrayPipelinePlugin.extend | |
| observeProperties: ['name', 'title'] | |
| process: (array) -> | |
| # Write sorting function here | |
| # Return result array | |
Initial impressions:I think to do incremental changes you need to break it into 3 separate in-order checks per item.
- shouldInclude
- applyTransforms (similar to objectAtContent)
- whatIndex (where in _results the list should end up at)
I'd implement an ArrayPipelineMixin that could be used on ArrayProxies and took the proxied incremental events from the built in array observers to respond to increment array changes.
for each item, you'd run these checks on each pipeline plugin, until you run into a case where shouldInclude is false.
Each plugin would then alter it's _results as needed based on the results of these checks.
Concerns:
This is more memory hungry and likely somewhat more cpu heavy than accomplishing the same thing in something like ArrangableMixin as you'd have to keep a copy of some form of the array for each pipeline plugin. But if you're trying to chain filters with ArrangableMixin this is already the case.
A little bit of context here:
The current SortableMixin / FilterMixin does not allow chaining in an easy way. I am proposing the creation of an Ember.ArrayPipeline that wraps the content of an Ember.Array(Proxy). The Ember.ArrayPipeline would allow you to register plugins that would be used for processing the contents of an Array.
A few concerns:
I have thoughts around how to address this concern, but I am also open to feedback. The current binarySearch implementation is a good example.
observationPropertychanging was in effect in the_observePropertiessectionHowever, if the observationProperties change upstream in the pipeline as a result of removing an observationProperty, it would make sense that the plugin being modified would not recalculate until passed a new in() array to process.
Unfortunately, I've run out of time to think about this (have to go back to work), but these are my first draft thoughts. Any feedback would be appreciated.