diff --git a/Guides/WAVE/README.md b/Guides/WAVE/README.md
index cc5efe69..08697574 100644
--- a/Guides/WAVE/README.md
+++ b/Guides/WAVE/README.md
@@ -4,4 +4,4 @@ Web Applications with Enhanced Views (Web, Pipeline, MVC, Filters etc.)
* Server-side [WAVE Server](Server.md)
* MVC [MVC](MVC.md)
-* Client-side Java Script Library [WAVE.js](WVJS.md)
+* Client-side Java Script Library [WAVE.js](WVJS/README.md)
diff --git a/Guides/WAVE/WVJS/ArrayFunctions.md b/Guides/WAVE/WVJS/ArrayFunctions.md
new file mode 100644
index 00000000..f97cdb09
--- /dev/null
+++ b/Guides/WAVE/WVJS/ArrayFunctions.md
@@ -0,0 +1,19 @@
+# Array functions
+
+##### arrayClear(array)
+Delete all elements from `array`.
+
+##### arrayDelete(array, object element): bool
+Delete `element` from `array` and return true if `element` was found.
+
+##### arrayShallowCopy(source_array): object
+Return new array - copy of `source_array`.
+
+##### arrayWalkable(array)
+Provides walking (see WAVE.Walkable) capability for array.
+
+##### groupWalkable(array)
+Converts array with {k : {}, v: []} structure to Walkable group operation result (inverse method to Walkable.wGroupToArray).
+
+##### inArray(array, object element): bool
+Returns true when `array` contains `element`.
diff --git a/Guides/WAVE/WVJS/EventManager.md b/Guides/WAVE/WVJS/EventManager.md
new file mode 100644
index 00000000..87a6c0b3
--- /dev/null
+++ b/Guides/WAVE/WVJS/EventManager.md
@@ -0,0 +1,29 @@
+# WAVE.EventManager
+Mixin that implements the event-handler mechanism and can be added to any class.
+
+##### eventInvocationSuspendCount: 0
+Increase to disable event firing for all events, decrease to enable, events are enabled again when value is <=0. This property is useful for batch updates to suppress many event firings that are not needed.
+
+##### eventBind(evtName, func)
+Binds a function to the named event handler.
+
+##### eventUnbind(evtName, func)
+Un-Binds a function from the named event handler.
+
+##### eventClear(evtName)
+Clears all functions from the named event handler.
+
+##### eventInvoke(evtName)
+Invokes all functions bound to the named event handler.
+
+##### eventSinkBind(sink)
+Binds a sink instance (an object) that will receive all events dispatched by this manager. The `sink` must have a function called `eventNotify(evtName, sender, args)` that will be invoked.
+
+##### eventSinkUnbind(sink)
+Un-Binds an object that received all events from this manager.
+
+##### eventSinkClear()
+Clears all objects that cat as event sinks bound to this instance.
+
+##### eventSinks()
+Returns a list of sink object that receive event notifications from this manager.
diff --git a/Guides/WAVE/WVJS/Field.md b/Guides/WAVE/WVJS/Field.md
new file mode 100644
index 00000000..71c7022d
--- /dev/null
+++ b/Guides/WAVE/WVJS/Field.md
@@ -0,0 +1,125 @@
+# Field Class
+Record consists of fields and Field represents a FieldDef from server-side NFX.DataAccess.CRUD.Schema on the client side along with view model/controller.
+
+## Field()
+Constructor. Initializes a new instance using string field definition and value.
+```js
+new rec.Field(object fieldDef)
+```
+### Examples
+```js
+var rec = new WAVE.RecordModel.Record("ID-123456", function(){
+ new this.Field({Name: "FirstName", Type: "string", Required: true});
+ new this.Field({Name: "LastName", Type: "string"});
+ new this.Field({Name: "Age", Type: "int"});
+ });
+```
+```js
+var rec = new WAVE.RecordModel.Record("ID-123456");
+new rec.Field({Name: "FirstName", Type: "string"});
+new rec.Field({Name: "LastName", Type: "string"});
+new rec.Field({Name: "Age", Type: "int", Stored: false});
+```
+
+
+## drop()
+Deletes this field from the record.
+
+
+## deferValidation()
+Defer or NOT validation event while changing of field’s value.
+```js
+deferValidation(bool flag)
+```
+### Examples
+```js
+var rec = ...
+var elog = "";
+rec.fldLastName.deferValidation(true);
+rec.fldLastName.eventBind(WAVE.EventManager.ANY_EVENT, function(evtType, field, phase){
+ elog += "|"+evtType + field.name() + phase + field.value();
+ });
+rec.fldLastName.value("Brown");
+// elog = "|data-changeLastNamebeforeSmith|data-changeLastNameafterBrown"
+```
+```js
+var rec = ...
+var elog = "";
+rec.fldLastName.deferValidation(false);
+rec.fldLastName.eventBind(WAVE.EventManager.ANY_EVENT, function(evtType, field, phase){
+ elog += "|"+evtType + field.name() + phase + field.value();
+ });
+rec.fldLastName.value("Brown");
+// elog = "|data-changeLastNamebeforeSmith|validateLastNameundefinedBrown|validatedLastNameundefinedBrown|data-changeLastNameafterBrown"
+```
+
+
+## eventBind()
+Binds a function to the named event handler on field.
+```js
+eventBind(string evtName, function handler)
+```
+| Parameter | Requirement | Description |
+| --------- |:-----------:| --------------------------------------------- |
+| evtName | required | name of event from WAVE.RecordModel namespace |
+| handler | required | callback-function which fires on event |
+### Examples
+```js
+var rec = ...
+var elog = "";
+rec.eventBind(WAVE.RecordModel.EVT_FIELD_DROP, function(field, phase){
+ elog += "|" + field.name() + phase;
+ });
+rec.fldLastName.drop();
+// elog = |LastNamebefore|LastNameafter
+```
+
+
+## isGUIModified()
+Returns true when this field was modified from an attached control.
+
+
+## isModified()
+Returns true when this field has been modified.
+
+
+## loaded()
+Returns true when this field has finished loading.
+
+
+## toString()
+Returns string like `[fieldType]Field(fieldName = 'fieldValue')`.
+
+
+## stored()
+Returns true if field must be stored back in the server (db).
+
+
+## Validation functions
+* valid() - returns true if field has not validation error.
+* validate() - validates field and returns true if it is valid.
+* validated() - returns true if field has been validated.
+* validationError() - returns error thrown during validation.
+### Examples
+```js
+var rec = new WAVE.RecordModel.Record("1", function(){
+ new this.Field({Name: "A", Type: "string"});
+ new this.Field({Name: "B", Type: "string", Required: true});
+ });
+
+rec.fldB.validated(); // false
+rec.fldB.validate();
+rec.fldB.validated(); //true
+rec.fldB.valid(); // false
+var err = rec.fldB.validationError(); // contains: 'B' must have a value
+rec.fldB.value("aaaaa");
+rec.fldB.valid(); // true
+```
+
+
+## value()
+`value()` - then returns field’s value.
+`value(object value, bool fromGUI)` - Sets value and modified, validated flags if new value is different from an existing one. `fromGUI` indicates that field is being altered from an attached control.
+
+
+
diff --git a/Guides/WAVE/WVJS/OperObjFunc.md b/Guides/WAVE/WVJS/OperObjFunc.md
new file mode 100644
index 00000000..052749d4
--- /dev/null
+++ b/Guides/WAVE/WVJS/OperObjFunc.md
@@ -0,0 +1,41 @@
+# Operations with objects and functions
+
+##### clone(object obj): object
+Deep clones data object (not functions).
+
+##### extend(object obj, object ext, bool keepExisting): object
+Mixin behavior - extends `obj` with properties of `ext`.
+If flag `keepExisting=true` then existing object key is preserved, even if it is null.
+
+##### isArray(object obj): bool
+Returns true when the passed parameter is an array, not a map or function.
+
+##### isFunction(object obj): bool
+Returns true when the passed parameter is a function, not a map object or an array.
+
+##### isMapOrArray(obj): bool
+Returns true when the passed parameter is an array, or map but not a function.
+
+##### isObject(object obj): bool
+Returns true when the passed parameter is a map, not an array or function.
+
+##### isSame(object obj1, object obj2): bool
+Returns true if both objects represent the same scalar value or complex structure/map that is keys/values of maps/arrays. Nulls are considered equivalent.
+
+##### overrideFunction(function original, function fn): function
+Overrides existing function by wrapping in new one. May call base like so:
+```js
+object.about = WAVE.overrideFun(object.about, function(){ return this.baseFunction() + "overridden" });
+```
+
+##### propStrAsObject(object obj, string prop)
+Checks object property for string value and if it is then converts it to object (map).
+Does nothing if prop does not exist, is null or not a string value.
+```js
+var o1 = {a: 1, b: '{"c": "yes", "d": "no"}'};
+// WAVE.isObject(o1.b)) = false
+
+WAVE.propStrAsObject(o1, "b");
+// WAVE.isObject(o1.b)) = true
+```
+
\ No newline at end of file
diff --git a/Guides/WAVE/WVJS/README.md b/Guides/WAVE/WVJS/README.md
new file mode 100644
index 00000000..a3e2f011
--- /dev/null
+++ b/Guides/WAVE/WVJS/README.md
@@ -0,0 +1,35 @@
+# NFX Wave.js
+Java Script Client Library
+
+## General-Purpose Functions
+
+#### [Array functions](ArrayFunctions.md)
+#### [Operations with objects and functions](OperObjFunc.md)
+#### [String functions](StringFunctions.md)
+
+## Sub-libraries and mixins
+#### [Geometry](geometry.md)
+Contains a large number of functions to work with geometry tasks.
+
+#### [EventManager](EventManager.md)
+Mixin that implements the event-handler mechanism and can be added to any class.
+
+#### SVG
+Provides working with SVG objects.
+
+#### [UTest](UTest.md)
+Implementation of unit testing concept.
+
+#### [Walkable](walkable.md)
+Mixin that enables function chaining that facilitates lazy evaluation via lambda-functions.
+
+
+## Record Model
+Record model is in the WAVE.RecordModel namespace.
+
+### Classes
+##### [Record](Record.md)
+##### [Field](Field.md)
+##### [RecordView](RecordView.md)
+
+
diff --git a/Guides/WAVE/Record/readme.md b/Guides/WAVE/WVJS/Record.md
similarity index 90%
rename from Guides/WAVE/Record/readme.md
rename to Guides/WAVE/WVJS/Record.md
index 89c10ff0..10928196 100644
--- a/Guides/WAVE/Record/readme.md
+++ b/Guides/WAVE/WVJS/Record.md
@@ -42,20 +42,6 @@ var rec = new WAVE.RecordModel.Record({ID: 'REC-1',
]});
```
-
-### Examples
-```js
-var rec = new WAVE.RecordModel.Record("1", function(){
- new this.Field({Name: "A", Type: "string"});
- new this.Field({Name: "B", Type: "string", Required: true});
- });
-
-rec.validate();
-var allErr = rec.allValidationErrorStrings();
-// allErr contains: 'B' must have a value
-```
-
-
## data()
Returns a map of fields: `{fieldName:fieldValue,...}`.
@@ -84,7 +70,6 @@ var d = JSON.stringify(rec.data(true));
// d = {"LastName":"Brown"}
```
-
## eventBind()
Binds a function to the named event handler on record.
```js
@@ -126,15 +111,12 @@ var v = rec.fldFirstName.value();
// v = John
```
-
## loaded()
Returns true when record has finished loading data and constructing fields.
-
##toString()
Returns string like `Record[RecID]`.
-
## Validation functions
* allValidationErrorStrings() - returns all record and field-level validation errors.
* validate() - validates record and returns true is everything is valid.
@@ -151,5 +133,3 @@ var all = rec.allValidationErrorStrings();
// all contains 'B' must have a value
// all contains 'C' must have a value
```
-
-
diff --git a/Guides/WAVE/RecordView/readme.md b/Guides/WAVE/WVJS/RecordView.md
similarity index 100%
rename from Guides/WAVE/RecordView/readme.md
rename to Guides/WAVE/WVJS/RecordView.md
diff --git a/Guides/WAVE/WVJS/StringFunctions.md b/Guides/WAVE/WVJS/StringFunctions.md
new file mode 100644
index 00000000..76255bdb
--- /dev/null
+++ b/Guides/WAVE/WVJS/StringFunctions.md
@@ -0,0 +1,130 @@
+# String functions
+
+##### charIsAZLetterOrDigit(char c): bool
+Returns true if `c` is `[a-zA-Z0-9]`.
+
+##### intValid(string val): bool
+Returns true if `val` is valid integer number.
+
+##### intValidPositive(string val): bool
+Returns true if `val` is valid positive integer number.
+
+##### intValidPositiveOrZero(string val)
+Returns true if `val` is valid positive integer number or zero.
+
+##### siNum(number num, int decimalPlaces): string
+Converts `num` to its string representation in SI (Le Systeme International d’Unites) with precision desired. `1000 = "1.00k", .1="100.00m", 23.55 = "23.55", 999.999="1.00k"`.
+
+##### strCaps(string s, bool normalize): string
+Capitalizes first chars after spaces or dots, optionally converting chars in between to lower case.
+
+##### strContains(string str, string seg, bool considCase): bool
+Returns true when `str` contains a `seg` optionally respecting case.
+
+##### strDefault(string s, string dflt): string
+If `s` is null or undefined then assigns `dflt` to it. If `dflt` is null or undefined then empty string.
+
+##### strEmpty(string s): bool
+Returns true if string is undefined, null or empty.
+
+##### strEnsureEnding(string s, string ending): string
+Ensures that string ends with the specified string: `strEnsureEnding("path",'/')`.
+
+##### strOneOf(string str, array set, string del): bool
+Returns true if the case-insensitive trimmed string is in the set of values. Neither string nor set value may contain delimiter which is '|' by default: `strOneOf("car", ["car", "house", "tax"], ';')`.
+
+##### strTrim / strLTrim / strRTrim(string s): string
+Remove spaces from both/left/right sides of `s`.
+
+##### strTrunc(string s, int maxLen, string endWith): string
+Truncates `s` if its length exceeds `maxLen` and adds `endWith` string to result end.
+
+##### strSame(string str1, string str2): bool
+Returns true if both string contain the same trimmed case-insensitive value. This method is useful for tasks like searches of components by name.
+
+##### strStartsWith / strEndsWith(string str, string seg, bool considCase): bool
+Returns true if `str` starts/ends with `seg` optionally respecting case.
+
+##### strEscapeHTML(content): string
+Replace html escape characters in `content` with special entities: `& --> &`.
+
+##### strHTMLTemplate(string tpl, object args): string
+Returns content like `'
@name@ | ' --> 'Alex & Helen | '` provided that `args = {name: 'Alex & Helen'}`. Data is HTML escaped.
+
+##### strTemplate(string tpl, object args): string
+Returns content like `'{a: "@name@"}' -> '{a: "Alex & Boris"}'` provided that `args = {name: 'Alex & Boris'}`. Data is not HTML escaped.
+
+##### strIsEMail(string str): bool
+Returns true if `str` is valid email like `a@bc.de`
+
+##### isValidScreenNameLetter(char c): bool
+Returns true if `c` is allowable screen symbol including diacritic.
+
+##### isValidScreenNameLetterOrDigit(char c): bool
+Returns true if `c` is number (0-9) or allowable screen symbol including diacritic.
+
+##### isValidScreenNameSeparator(char c): bool
+Returns true if `c` is one from following set: ['.', '-', '_'].
+
+##### strIsScreenName(string s): bool
+Returns true if `s` contains valid screen name/ID.
+
+##### strNormalizeUSPhone(string s)
+Normalizes US phone string so it looks like (999) 999-9999x9999. If `s` starts with '+'(international phone, just return as-is).
+
+##### strLocalize(string iso, string schema, string fld, string val): string
+Localizes string per supplied lang iso code within schema/field.
+
+##### toISODateTimeString(datetime dt): string
+Returns '`dt` as string in ISO format (e.g. "2012-01-22T12:30:15.120Z").
+
+##### toUSDateTimeString(datetime dt): string
+Returns `dt` as string in "MM/DD/YYYY HH:MM:SS" format.
+
+##### toUSDateString(datetime dt): string
+Returns `dt` as string in "MM/DD/YYYY" format.
+
+##### toSeconds(string dur): int
+Parses duration string to total seconds. Example of duration string: "1d 10h 7m 13s".
+
+##### genRndKey(int keyLen, string alphabet): string
+Generates random key with specified length from the alphabet of possible characters: `rndKey(10,"abcdefzq2")`.
+
+##### genAutoincKey(string seq, int val)
+Returns next value of named sequence as result of: previous value (0 if function was not called for this sequence) + val.
+
+##### isScalar(val): bool
+Returns true for scalar vars and false for arrays and objects.
+
+##### rnd(int min, int max): int
+Returns random number in the range of min/max where min=0 max=100 by default: `rnd(10,57); rnd(30);`
+
+##### id(string s): object
+`document.getElementById(s)`.
+
+##### getCookie(string name): string
+Returns cookie by name or false if not found;
+
+##### setCookie(string name, string value)
+Set cookie as `name = escape(value) + "; path=/"`.
+
+##### deleteCookie(string name)
+Set expires as -1.
+
+##### Checking types
+Returns true if `tp` is in:
+* **isObjectType(tp)** - ["object", "json", "map", "array"]
+* **isIntType(tp)** - ["int", "integer"]
+* **isRealType(tp)** - ["float", "real", "double", "money"]
+* **isBoolType(tp)** - ["bool", "boolean", "logical"]
+* **isStringType(tp)** - ["str", "string", "char[]", "char", "varchar", "text"]
+* **isDateType(tp)** - ["date", "datetime", "time", "timestamp"]
+
+##### convertScalarType(bool nullable, scalar value, string type, scalar dflt)
+Converts scalar value into the specified type:
+```js
+var v;
+v = convertScalarType(false, 13, "string", ""); // v = '13'
+v = convertScalarType(true, "13", "int"); // v = 13
+v = convertScalarType(false, "abc", "int", 10); // v = 10
+```
\ No newline at end of file
diff --git a/Guides/WAVE/WVJS/UTest.md b/Guides/WAVE/WVJS/UTest.md
new file mode 100644
index 00000000..1498fd83
--- /dev/null
+++ b/Guides/WAVE/WVJS/UTest.md
@@ -0,0 +1,26 @@
+# WAVE.UTest
+Static class which implements unit testing concept.
+
+##### run(string area, string name, function fn)
+Wrapper for testing statements which placed in `fn`.
+```js
+run("Assertions", "assertTrue", function(){
+ assertTrue(true);
+ log("This must pass 1");
+});
+```
+
+##### testingStarted()
+Returns true to indicate that testing has been activated.
+
+##### log(string msg)
+Writes log message in new line.
+
+##### logi(string msg)
+Writes log message inline.
+
+##### assertTrue(bool assertion, string msg)
+If bool statement `assertion` is not true, then throws exception with `msg` ("Assertion not true" if empty).
+
+##### assertFalse(bool assertion, string msg)
+If bool statement `assertion` is not false, then throws exception with `msg` ("Assertion not false" if empty).
diff --git a/Guides/WAVE/WVJS/geometry.md b/Guides/WAVE/WVJS/geometry.md
new file mode 100644
index 00000000..c96f640f
--- /dev/null
+++ b/Guides/WAVE/WVJS/geometry.md
@@ -0,0 +1,141 @@
+# WAVE.Geometry
+
+## Properties
+
+* EARTH_RADIUS_KM : 6371
+* PI : 3.14159265
+* PI2 : 6.28318531
+* MapDirection:
+{
+ North: {Name: "North"},
+ NorthEast: {Name: "NorthEast"},
+ East: {Name: "East"},
+ SouthEast: {Name: "SouthEast"},
+ South: {Name: "South"},
+ SouthWest: {Name: "SouthWest"},
+ West: {Name: "West"},
+ NorthWest: {Name: "NorthWest"}
+}
+
+
+## Functions
+
+##### angleToMapDirection(double angle): MapDirection
+Converts a radian angular coordinate into map direction
+##### azimuthDeg(double xc, double yc, double xd, double yd): double
+Returns azimuth angle (theta) in degrees.
+##### azimuthDegPoints(Point pc, Point pd)
+Returns azimuth angle (theta) in degrees for two points: center and destination.
+##### azimuthOfRadix(double xc, double yc, double xd, double yd, int radix): int
+Returns azimuth angle (theta) in radix units.
+##### azimuthOfRadixPoints(Point pc, Point pd, int radix): int
+Returns azimuth angle (theta) in in radix units for two points: center and destination .
+##### azimuthRad(double xc, double yc, double xd, double yd): double
+Returns azimuth angle (theta) in radians.
+##### azimuthRadPoints(Point pc, Point pd)
+Returns azimuth angle (theta) in radians for two points: center and destination.
+##### degToRad(int deg): double
+Converts degrees to rads.
+##### distance(double x1, double y1, double x2, double y2): double
+Returns pixel distance between two points.
+##### distancePoints(Point p1, Point p2): double
+Returns pixel distance between two points.
+##### findRayFromRectangleCenterSideIntersection(Rectangle rect, double theta): Point
+Returns a point of intersection between a ray cast from the center of a rectangle under certain polar coordinate angle and a rectangle side.
+##### getBBox(points): Rectangle
+Returns 2D bounding box (with for a set of points (array of {x, y}).
+##### lineIntersectsRect(double rx1, double ry1, double rx2, double ry2, double lx1, double ly1, double lx2, double ly2): bool
+Defines if line has common points with rectangle (top-left/bottom-right coordinates).
+##### mapDirectionToAngle(MapDirection direction): double
+Converts map direction to angular coordinate in radians.
+##### overlapAreaRect(Rectangle rect1, Rectangle rect2): double
+Returns area of overlap between two rectangles.
+##### overlapAreaWH(double x1, double y1, double w1, double h1, double x2, double y2, double w2, double h2): double
+Returns area of overlap between two rectangles expressed as top-left/width-height pairs.
+##### overlapAreaXY(double left1, double top1, double right1, double bott1, double left2, double top2, double right2, double bott2): double
+Returns area of overlap between two rectangles expressed as top-left/bottom-right pairs.
+##### perimeterViolationArea(Rectangle perimeter, Rectangle inner): double
+Calculates a relative area of an inner rectangle that violates outside perimeter. The area is not 100% geometrically accurate - may be used for relative comparisons only.
+##### radToDeg(double rad): double
+Converts radians to degrees.
+##### rotateRectAroundCircle(double cx, double cy, double cMargin, double rw, double rh, double angle): Rectangle
+Calculates coordinates of rectangle given by width/height (`rw/`rh`) which center is rotated by `angle` (in radians) relatively to point (`cx`/`cy`) respecting rectangle size and `cMargin`. Returns coordinates of rotated rectangle.
+##### toRectWH(double x1, double y1, double w, double h): Rectangle
+Returns rectangle from coordinates and dimensions (width and height).
+##### toRectXY(double x1, double y1, double x2, double y2): Rectangle
+Returns rectangle from coordinate pairs.
+##### vectorizeBalloon(Rectangle body, Point target, double legSweep)
+Calculates call out balloon vertices suitable for contour curve drawing. Returns an array of vertex points.
+* body - Balloon body coordinates.
+* target - Balloon leg attachment point
+* legSweep - Length of balloon leg attachment breach at balloon body edge, expressed in radians (arc length). A value such as PI/16 yields good results.
+##### wrapAngle(double angle, double delta): double
+Modifies an angle by delta value ensuring that resulting angle is always between 0 and 2pi.
+
+
+## Classes
+
+### Point
+Represents x,y pair on a Cartesian plane.
+##### Point(double x, double y)
+Constructor.
+##### isEqual(Point p): bool
+Determines whether the two points contain equivalent coordinates.
+##### offset(double dx, double dy)
+Changes point coordinates.
+##### toPolarPoint(Point center): PolarPoint
+Returns point as polar point relative to the specified center.
+##### toString(): string
+Returns coordinates in string like: `(10 , 12)`.
+##### x(double val): double
+Sets/returns X coordinate.
+##### y(double val): double
+Sets/returns Y coordinate.
+
+### PolarPoint
+Represents point with polar coordinates.
+##### PolarPoint(double radius, double theta)
+Constructor.
+##### isEqual(PolarPoint p): bool
+Determines whether the two points contain equivalent coordinates.
+##### radius(double val): double
+Sets/returns radius of point.
+##### theta(double val): double
+Sets/returns angle theta of point.
+##### toPoint(): Point
+Returns polar point as simple Cartesian (x,y) point.
+##### toString(): string
+Returns coordinates in string like: `(1 , 45°)`.
+
+### Rectangle
+Represents a rectangle.
+##### Rectangle(Point corner1, Point corner2)
+Constructor.
+##### bottom(): double
+Returns bottom-most edge coordinate.
+##### bottomRight(): Point
+Returns bottom right corner point per natural axis orientation when X increases from left to right, and Y increases from top to bottom.
+##### centerPoint(): Point
+Returns center point.
+##### contains(Point p): bool
+Tests if point lies within this rectangle.
+##### corner1(Point val): Point
+Sets/returns top left corner of rectangle.
+##### corner2(Point val): Point
+Sets/returns bottom right corner of rectangle.
+##### height(): double
+Returns rectangle height.
+##### left(): double
+Returns left-most edge coordinate.
+##### right(): double
+Returns right-most edge coordinate.
+##### square(): double
+Returns rectangle square.
+##### top(): double
+Returns top-most edge coordinate.
+##### topLeft(): Point
+Returns top left corner point per natural axis orientation when X increases from left to right, and Y increases from top to bottom.
+##### width(): double
+Returns rectangle width.
+
+
diff --git a/Guides/WAVE/WVJS/walkable.md b/Guides/WAVE/WVJS/walkable.md
new file mode 100644
index 00000000..d9eee993
--- /dev/null
+++ b/Guides/WAVE/WVJS/walkable.md
@@ -0,0 +1,229 @@
+# WAVE.Walkable
+Mixin that enables function chaining that facilitates lazy evaluation via lambda-functions. This is analogue of method-based LINQ queries in .NET.
+
+## Projection Operations
+##### wSelect(transform)
+Projects values that are based on a transform function.
+```js
+var a = [1, 2, 3];
+var aw = WAVE.arrayWalkable(a);
+var wSelect = aw.wSelect(function(e) { return e * 10; });
+var result = wSelect.wToArray(); // [10, 20, 30]
+```
+
+##### wSelectMany(transform)
+Projects sequences of values that are based on a transform function and then flattens them into one sequence.
+```js
+var a0 = [1, 2];
+var a1 = [3, 4];
+
+var aa = [WAVE.arrayWalkable(a0), WAVE.arrayWalkable(a1)];
+var aw = WAVE.arrayWalkable(aa);
+var result = aw.wSelectMany(function (e) { return e; });
+
+// result.wAt(0) = 1
+// result.wAt(1) = 2
+// result.wAt(2) = 3
+// result.wAt(3) = 4
+```
+
+## Filtering Data
+##### wWhere(filter)
+Selects values that are based on a predicate function `filter`.
+```js
+var a = [1, 2, 3, 4, 5];
+var aw = WAVE.arrayWalkable(a);
+var whereWalkable = aw.wWhere(function(e) { return e > 3; });
+var resultArray = whereWalkable.wToArray(); // [4, 5]
+```
+
+
+## Element Operations
+##### wAt(int pos)
+Returns the element at a specified index in a walkable collection.
+
+#### wEach(action)
+Does `action` for each element in collection.
+
+##### wFirst(condition)
+Returns the first element of a collection, or the first element that satisfies a condition.
+```js
+var a = [1, 2, 3];
+var aw = WAVE.arrayWalkable(a);
+var first;
+
+first = aw.wFirst(); // 1
+first = aw.wFirst(function(e) { return e > 2; }); // 3
+first = aw.wFirst(function(e) { return e < 0; }); // null
+
+aw = WAVE.arrayWalkable([]);
+var cnt = aw.wFirst(); // null
+```
+
+##### wFirstIdx(condition)
+Returns an index of element that satisfies a condition.
+```js
+var a = [1, 2, 3];
+var aw = WAVE.arrayWalkable(a);
+var idx;
+idx = aw.wFirstIdx(function(e) { return e == 0; }); // -1
+idx = aw.wFirstIdx(function(e) { return e == 1; }); // 0
+```
+
+
+## Aggregation Operations
+##### wAggregate(aggregate, initVal)
+Performs a custom aggregation operation on the values of a collection.
+
+##### wCount(condition)
+Counts the elements in a collection, optionally only those elements that satisfy a predicate function.
+
+##### wMax(greater)
+Determines the maximum value in a collection.
+
+##### wMin(less)
+Determines the minimum value in a collection.
+
+##### wSum(initVal)
+Calculates the sum of the values in a collection.
+
+
+## Set Operations
+#### wConcat(other)
+Concatenates two sequences to form one sequence.
+```js
+var aw = WAVE.arrayWalkable([1, 2, 3]);
+var bw = WAVE.arrayWalkable([5, -4]);
+var ct = aw.wConcat(bw).wToArray(); // [1, 2, 3, 5, -4]
+```
+
+##### wDistinct(equal)
+Returns distinct elements from a sequence by using the default equality comparer or `equal` to compare values.
+```js
+var a = [1, 2, 2, 3, 5, 4, 2, 4, 3];
+var aw = WAVE.arrayWalkable(a);
+var distinct = aw.wDistinct();
+var result = distinct.wToArray(); // [1, 2, 3, 5, 4]
+```
+```js
+var a = [{x: 0, y: 0}, {x: 1, y: 1}, {x: 2, y: 1}, {x: 3, y: 1}, {x: 4, y: 3}];
+var aw = WAVE.arrayWalkable(a);
+var distinct = aw.wDistinct(function(a, b) { return a.y == b.y; });
+var result = distinct.wToArray(); // [{x: 0, y: 0}, {x: 1, y: 1}, {x: 4, y: 3}]
+```
+
+##### wExcept(other, equal)
+Produces the set difference of two sequences by using the default equality comparer or `equal`.
+```js
+var a = [1, 2, 3];
+var b = [2];
+var aw = WAVE.arrayWalkable(a);
+var bw = WAVE.arrayWalkable(b);
+var except = aw.wExcept(bw).wToArray(); // [1, 3]
+```
+
+#### wEqual(other, equalFunc)
+Determines whether two sequences are equal by comparing elements with `equalFunc`(optional).
+
+## Grouping Data
+##### wGroup(keyer, valuer)
+Groups elements that share a common attribute. Result has `k` (key) and `v` (values) properties.
+```js
+var a = [{x: 0, y: 0}, {x: 1, y: 1}, {x: 0, y: 33}, {x: 0, y: 34}, {x: 1, y: -5}, {x: 0, y: 127}];
+
+var group = WAVE.arrayWalkable(a).wGroup(function(e) { return e.x; }, function(e) { return e.y; }).wGroupIntoArray();
+/*
+group[0].k = 0
+group[0].v.length = 4
+group[0].v[0] = 0
+group[0].v[1] = 33
+group[0].v[2] = 34
+group[0].v[3] = 127
+
+group[1].k = 1
+group[1].v.length = 2
+group[1].v[0] = 1
+group[1].v[1] = -5
+*/
+```
+
+##### wGroupAggregate(aggregator, initVal)
+Performs a custom aggregation operation on the elements in groups.
+```js
+var a = [{x: 0, y: 0}, {x: 1, y: 1}, {x: 0, y: 33}, {x: 0, y: 34}, {x: 1, y: -5}, {x: 0, y: 127}];
+
+var group = WAVE.arrayWalkable(a).wGroup(function(e) { return e.x; }, function(e) { return e.y; }).wGroupAggregate(function(k, r, e) { return (r || 0) + e });
+
+// group.wAt(0).v = 194
+// group.wAt(1).v = -4
+```
+
+##### wGroupIntoArray()
+Converts the result of grouping to array of objects like this: `{k: key, v: [values]}`
+
+##### wGroupIntoObject()
+Converts the result of grouping to object like this: `obj[key] = [values]`.
+
+## Sorting Data
+##### wOrder(order)
+Sorts elements in according to `order`.
+```js
+var a = [1, -3, 2, 17, -9, 4, 5];
+var ordered = WAVE.arrayWalkable(a).wOrder(function(a, b) { return a < b ? 1 : a > b ? -1 : 0; }).wToArray();
+// ordered = [17, 5, 4, 2, 1, -3, -9]
+```
+
+## Partitioning Data
+##### wTake(quantity)
+Takes `quantity` elements from the head of collection.
+
+##### wTakeWhile(condition)
+Takes elements from the head of collection while `condition` is true.
+
+##### wSkip(quantity)
+Skips `quantity` elements from the head of collection.
+
+## Quantifier Operations
+##### wAny(condition)
+Determines whether any elements in a sequence satisfy a condition.
+
+##### wAll(condition)
+Determines whether all the elements in a sequence satisfy a condition.
+
+
+## Converting Data Types
+#### wToArray()
+Converts a collection to an array.
+
+## Special Operations
+#### wHarmonicFrequencyFilter(m, k)
+Frequency filter takes:
+* "m" (f=ma Newtons law) - in virtual units of mass (i.e. kilograms) - the higher the number the more attenuation for high frequencies,
+* "k" (f=-kx Hooks law) - in virtual units of spring membrane resistance, the higher the number the more attenuation for low frequencies.
+
+##### wConstLinearSampling(samplingStep)
+Ensures that all {s, a} vectors in incoming walkable are equally spaced in time, so {a} component linearly interpolated between otherwise discrete points, i.e. [ {1, -47} , {10, 150}] => F(2) => yields vectors where respected components (0 -> 5, -47 -> 150) get linearly pro-rated.
+```js
+var w = WAVE.arrayWalkable([{s: 1, a: 10}, {s: 10, a: 700}]).wConstLinearSampling(2);
+w.wAt(0).s = 0
+w.wAt(0).a = 10
+```
+
+#### wSineGen / wSawGen / wSquareGen / wRandomGen(cfg)
+Outputs {s,a} vectors per SINE/"Saw"/"Square"/Random function.
+
+#### wWMA(k)
+"weight"-based moving average filter (k is kind of "weight" 0..1):
+* if k == 0 - moving object has no weight (hence no momentum) and outbound signal is the same as inbound,
+* if k == 1 - moving object has infinite weight (hence infinity momentum) and outbound signal will be permanent (equal to first sample amplitude).
+```js
+var aw = WAVE.arrayWalkable([{s: 0, a: 1}, {s: 1, a: 100}, {s: 2, a: -100}]);
+var wma = aw.wWMA(.1);
+// wma.wAt(0).a = 1
+// wma.wAt(1).a = 90.1
+// wma.wAt(2).a = -80.99
+```
+
+##### WAVE.signalConstSrc(cfg)
+ Walkable source of constant signal: `WAVE.signalConstSrc({a: 17.75, qty: 2})`.
+
\ No newline at end of file