Releases: karfcz/kff
Releases · karfcz/kff
Version 3.0.0-alpha.4
- Refresh on requestAnimationFrame by default
- Actions can return function that gets called immediately with the dispatch argument (allowing async actions)
- Other minor changes
Version 3.0.0-alpha.2
First alpha release of the third major version, completely reworked and slimmed down.
- Removed models, collections, DI container, App class, Dom class, front controller, PageView, router, ViewFactory, and much more,
- Use of immutable state via cursors. Actions, event streams and flux-like global refresh lifecycle.
Version 2.0.0
Version 2.0.0-alpha.2
- BREAKING CHANGE: When rerendering a view in collection binding with new model data, the view is not destroyed/rerendered from scratch but the new models are passed to the view and its
refresh
method is called so that the view can refresh only DOM elements that really change. All internal bindings work that way but any user defined views that work with models or the DOM explicitly must implement therefresh
method to rebind changed models and project changes into the DOM. - A new method
kff.View#refreshAll
does cascading refresh of the view tree. - Better algorithm for diff collection and bindings refreshing/rerendering. No more superfluous rerendering of views. A new template
kff.View#refresh
method is used to update the view. Note that it's up to the view to determine if it needs to refresh. - Data bindings work with plain JS object as well. Plain object bindings are not watched, any change have to be manually rerendered by the refreshAll method.
- Collection binding can work with plain arrays. The new ':each' modifier must be used to indicate 'array as collection' binding, because array can be also used as attribute value (for example in multiple select). Array binding is not watched, any change have to be manually rerendered by the refreshAll method.
- Helpers (parsers and formatters in views) can now be passed to individual views in constructor using DI. Old global register method is now obsolete. Helpers also have their own scope in view hierarchy similar to the model scope, so any subview has immediate access to helpers from any parent view.
- A new binder modifier :evf (eventFilter) to process DOM events through a function. The filter function must be registered in
helpers
view option. The filter function must accept two arguments: 'fn' - the original event handler and 'event' - the original DOM event. When the event is accepted, the function must call the original handler: fn.call(this, event). - A new binding modifier ':nopreventdef' to suppress calling event.preventDefault in DOM event handler.
- A new binder (kff.CallBinder aka
:call
) that calls a method of a model with arguments. The attribute part of model path must be a valid model method. Arguments can be plain strings (processed by implicit type conversion) or models from the current scope (prefixed with @ char). - Implicit conversion of basic data types from bindings. Used to process any values from binding attributes. It is not used to process DOM values (such as input value). Conversions are as follows:
"null" => null
"true" => true
"false" => false
"42" => 42
(convert number in string to number)
- New binders (kff.IfBinder -
:if
, kff.IfNotBinder -:ifnot
) that insert/remove view element to/from the DOM. They work like the 'insert' binder with a new cleaner syntax. These binders destroy all subviews when removing view element from the DOM and rerender them when inserting. They do not render any subviews during the initial render phase. Both:if
and:ifnot
binders have default condition valuetrue
. - A new
:classnot
binder that works like the:class
binder but works in opposite way - it removes the class when the value is true. Both:class
and:classnot
binders now have default condition valuetrue
. - Primitive types (string, number and boolean) can be used as models (it has only limited use case such as fast rendering of long list of values)
- A new option called 'regions' is now available in views. It should be a plain object that contains key-value pairs in form of 'css selector': 'html template string'. When the page view is rendered (before render method), each html template is inserted into the DOM node(s) matching the css selector. If the node is not empty, its content is cached in a temporary document fragment and it is inserted back to the node when the view is being destroyed. So the overlaying page views can even overwrite regions of previous views without damaging entire app. A special selector
self
is used to insert HTML template directly into the view element. Theself
selector is always rendered before any other regions so that they can reference DOM elements from the 'self' template. - Page views and app can be bound to any DOM element, not just body and document.
- Added ability to destroy app, front controller and state handler.
- Eliminated dependency for document and window objects in views. Removing dependencies for global browser objects is an important step for server side rendering in node.js environment. Document and window objects are now passed in
env
object as a option in views, app and front controller. Note that the globals are still used in polyfills, but these are not used in node. - Implemented a simple module dependency system for resolving "static" dependencies like class extends. Function
kff.define
defines a module with dependencies.kff.require
returns module while resolving and injection all the dependencies. It works in similar way like the AMD but can be used together with DI container. Service container now tries to resolve any dependency usingkff.require
with fallback to global object look up when it fails. - Preliminary support for routing "middlewares" (experimental feature)
- Added simple debug mode. When the
kff.debug
property is set to true, then some warnings are logged into console (such as missing views). - Merged kff.BindingView class into kff.View class. Collection binding methods were moved into a separate class.
- Implemented a new
dispatch
binder operator that passes DOM binding events to some sort of global dispatcher instead of pushing to the model directly (inspired by the Flux pattern). This allows things such as using immutable data without two-way binding instead of model and collection classes. This feature is still in experimental state and will change in the future. - Numerous fixes and optimizations
Version 2.0.0-alpha.1
- Significant rendering speed and memory optimizations
kff.BindingView
: implement counting of rendered (filtered) collection. Number of rendered collection items is propagated into an attribute of some model. Model + attribute are specified in element's attributedata-kff-count
usingmodel.attr
format. Every time a collection is rerendered, the count attribute is updated.kff.BindingView
: implement live sorting in collection binding. Live sorting (sorting of bound collection) is done in similar way as filtering. Sort function is specified in attributdata-kff-sort
usingmodel.compareFunction
format. It watches any change in collection or in collection item, which can lead to an overhead in some situations but DOM manipulation is done only on actual change in order, so it should not be critical.kff.BindingView
: diff based rerendering of collection bindings. When rendering filtered list, do not maintain index map of rendered items. Instead, create a new filtered collection and reuse already rendered nodes with new model items. This allows for better performance of heavily modified/filtered/sorted collections.kff.Binder
: experimental feature - when bound object is not an instance of kff.Model, render it as plain JS object (like:nobind
).kff.FrontController
: decouple hashchange observer from FrontController and provide separate service for state manipulation instead. A new service HashStateHandler provides legacyhashchange
event manipulation/listening. It can be easily replaced by HTML5 pushState API wrapper service or another state handler (i. e. state handler that works completely without url).- include IE8/9 polyfills (classList and standards compliant DOM events for IE8) into kff build
kff.createModelClass
: a new helper function that creates specific "model" class. This function creates a class constructor like the kff.createClass function but generates getter/setter function for every attribute.kff.Collection
: new methods corresponding to native array methods:concat
,join
,map
,reduce
,reduceRight
,slice
,push
,pop
,shift
,unshift
,kff.Collection
: filter method should be non-mutating + mutating behavior should be accomplished by remove method with function argument (BREAKING CHANGE)kff.Collection
: a new method 'createItem' for creating collection items using provided itemFactory or itemTypekff.ModelView
: a simple view class with implicit empty model accessible as*
in data bindings (just like an item in collection binding).- Simplified configuration of
kff.App
. It was necessary to create full FrontController and Router DI configuration to use router or non-default PageView. Now it is possible to use simpler App config. - make
:fill
binding mode work inside collection binding. When:fill
was used inside colelction binding, it wouldn't work because cloned input didn't have the original value anymore. To make it work, I get the input value in constructor and save it for later use in fill method (only when options.fill is set). - Removed internal
kff.List
class, all its behaviour is now merged intokff.Collection
- Removed all dependecies to jQuery
- add
nobind
modifier to binding syntax to slightly speed up rendering when no model od DOM changes are expected kff.View
: allow using model keypath in model events. When declaring model events, it should be possible to use model keypath as the first argument (not just model name), i.e.:
['foo.bar', 'change:attr', 'method]
kff.Binder
: add pseudo-param@attr
to getter and setterkff.InsertBinder
(orinsert
): a new binder for conditionally inserting/removing view element into/from the DOM- Getters and setters (:get and :set binding modifiers) now can take variable-length arguments. Arguments are evaluated as model keypaths in current view scope. If no argument are specified, legacy behaviour is used (= standard attr/val arguments).
kff.Router
: router now can fill url parameters to a model objectkff.Model
: addunsetAll
method for unsetting all model attributeskff.Model
: add methodunset
for unsetting (deleting) model attribute(s)kff.View
: added rerender method- prevent displaying
null
in binders in MSIE kff.StyleBinder
: add optional second argument for CSS unitstaticProperties
renamed to juststatics
in class definition- View rendering is splitted into two phase process: render (generating and traversing of DOM node of the view) and run (initialization of data-bindings and DOM/model events, actual running of the view). Those phases are triggered by methods renderAll and runAll (generates/runs the whole tree of views).
kff.ServiceContainer
now creates not only instances of classes (default) but also factory functions (type = 'factory'
), direct references to function objects (type = 'function'
) or even references to arbitrary javascript object (automatically detected).kff.ServiceContainer
function has a new optional parameter (loader), which is a function that accepts service name and returns service object (reference). The default loader searches for service in global window object. This can be used for getting services from browserify bundle or even from require calls in node.js. Note that the loader must be synchronous.