Skip to content

Commit 9c7eefa

Browse files
committed
Adapter assignments refactoring, specs and readme clarification
1 parent e029834 commit 9c7eefa

File tree

9 files changed

+96
-160
lines changed

9 files changed

+96
-160
lines changed

README.md

+11-4
Original file line numberDiff line numberDiff line change
@@ -148,11 +148,11 @@ It is empty since it was deprecated in v1.6.0.
148148
>{{item}}</div>
149149
```
150150

151-
### Parametrs
151+
### Parameters
152152

153153
* **uiScroll – scroll expression** – The expression indicating how to enumerate a collection. Only one format is currently supported: `variable in datasource` – where variable is the user defined loop variable and datasource is the name of the data source to enumerate.
154-
* **buffer-size - expression**, optional - number of items requested from the datasource in a single request. The default is 10 and the minimal value is 3
155-
* **padding - expression**, optional - extra height added to the visible area for the purpose of determining when the items should be created/destroyed. The value is relative to the visible height of the area, the default is 0.5 and the minimal value is 0.3
154+
* **buffer-size - expression**, optional - number of items requested from the datasource in a single request. The default is 10 and the minimal value is 3.
155+
* **padding - expression**, optional - extra height added to the visible area for the purpose of determining when the items should be created/destroyed. The value is relative to the visible height of the area, the default is 0.5 and the minimal value is 0.3.
156156
* **start-index - expression**, optional - index of the first item to be requested from the datasource. The default is 1.
157157
* **adapter - assignable expression**, optional - if provided a reference to the adapter object for the scroller instance will be injected in the appropriate scope. If you have multiple scrollers within the same viewport, make sure that every one of them has its unique adapter name.
158158

@@ -165,7 +165,14 @@ Some of the properties offered by the adapter can also be accessed directly from
165165

166166
The `expression` can be any angular expression (assignable expression where so specified). All expressions are evaluated once at the time when the scroller is initialized. Changes in the expression value after scroller initialization will have no impact on the scroller behavior.
167167

168-
The assignable expressions will be used by scroller to inject the requested value into the target scope. The scope associated with the viewport (the element marked with the [uiScrollViewport](#uiscrollviewport-directive) directive) will be used as the target scope. If the viewport is not defined (window viewport), the $rootScope will be used as the target scope. Also `Controller As` syntax could be used as an alternative way to specify target controller in assignable expressions.
168+
The `assignable expressions` will be used by scroller to inject the requested value into the target scope.
169+
The target scope is being defined in accordance with standard Angular rules (nested scopes and controller As syntax should be taken into account):
170+
the scroller will traverse its parents (from the ui-scroll element's scope up to the $rootScope) to locate the target scope.
171+
If the viewport is presented (the element marked with the [uiScrollViewport](#uiscrollviewport-directive) directive),
172+
then the scope associated with the viewport will be a start point in target scope detecting.
173+
Angular $parse service is being used in `assignable expressions` implementation.
174+
175+
_Deprecated!_ The format `expression on controller` introduced in v1.5.0 (and deprecated in v1.6.1) can be used to explicitly target the scope associated with the specified controller as the target scope for the injection. In this format `expression` is any angular assignable expression, and `controller` is the name of controller constructor function as specified in the `ng-controller` directive.
169176

170177
### Datasource
171178

demo/insideDirective/insideDirective.html

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ <h1 class="page-header page-header-exapmle">Scroller inside the directive</h1>
2222
</div>
2323

2424
<div ng-controller="mainController">
25-
<div ng-if="true">
25+
<div ng-if="show">
2626
<my-dir></my-dir>
2727
</div>
2828
</div>

dist/ui-scroll.js

+37-63
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ui-scroll.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ui-scroll.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/ui-scroll.min.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/modules/adapter.js

+37-62
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,6 @@
1-
function findCtrl(scope, ctrl) {
2-
if (!scope) {
3-
return;
4-
}
5-
if (scope.hasOwnProperty(ctrl) && Object.getPrototypeOf(scope[ctrl]).constructor.hasOwnProperty('$inject')) {
6-
return scope[ctrl];
7-
}
8-
return findCtrl(scope.$parent, ctrl);
9-
}
10-
11-
function assignAttr(attr, scope, element) {
12-
if (!attr || !(attr = attr.replace(/^\s+|\s+$/gm, ''))) {
13-
return;
14-
}
15-
1+
function getCtrlOnData(attr, element) {
162
let onSyntax = attr.match(/^(.+)(\s+on\s+)(.+)?/);
17-
let asSyntax = attr.match(/^([^.]+)\.(.+)?/);
18-
19-
if (onSyntax && onSyntax.length === 4) { // controller on (backward compatibility), deprecated since v1.6.1
3+
if (onSyntax && onSyntax.length === 4) {
204
window.console.warn('Angular ui-scroll adapter assignment warning. "Controller On" syntax has been deprecated since ui-scroll v1.6.1.');
215
let ctrl = onSyntax[3];
226
let tail = onSyntax[1];
@@ -34,61 +18,56 @@ function assignAttr(attr, scope, element) {
3418
}
3519
throw new Error('Angular ui-scroll adapter assignment error. Failed to locate target controller "' + ctrl + '" to inject "' + tail + '"');
3620
}
37-
else if (asSyntax && asSyntax.length === 3) { // controller as
38-
let ctrl = asSyntax[1];
39-
let tail = asSyntax[2];
40-
let foundCtrl = findCtrl(scope, ctrl);
41-
if (foundCtrl) {
42-
return {
43-
target: foundCtrl,
44-
source: tail
45-
};
46-
}
47-
}
48-
49-
return {
50-
target: scope,
51-
source: attr
52-
};
5321
}
5422

5523
class Adapter {
5624

57-
constructor(viewport, buffer, adjustBuffer, reload, $attr, $parse, element) {
25+
constructor(viewport, buffer, adjustBuffer, reload, $attr, $parse, element, $scope) {
5826
this.viewport = viewport;
5927
this.buffer = buffer;
6028
this.adjustBuffer = adjustBuffer;
6129
this.reload = reload;
6230

63-
this.publicContext = {};
64-
this.assignAdapter($attr, $parse, element);
65-
this.generatePublicContext($attr, $parse, element);
66-
6731
this.isLoading = false;
6832
this.disabled = false;
69-
}
7033

71-
assignAdapter($attr, $parse, element) {
72-
let data = assignAttr($attr.adapter, this.viewport.getScope(), element);
34+
const viewportScope = viewport.getScope();
35+
this.startScope = viewportScope.$parent ? viewportScope : $scope;
36+
37+
this.publicContext = {};
38+
this.assignAdapter($attr.adapter, $parse, element);
39+
this.generatePublicContext($attr, $parse);
40+
}
7341

74-
if (data) {
75-
try {
76-
$parse(data.source).assign(data.target, {});
77-
let adapterOnScope = $parse(data.source)(data.target);
42+
assignAdapter(adapterAttr, $parse, element) {
43+
if (!adapterAttr || !(adapterAttr = adapterAttr.replace(/^\s+|\s+$/gm, ''))) {
44+
return;
45+
}
46+
let ctrlOnData = getCtrlOnData(adapterAttr, element);
47+
let adapterOnScope;
7848

79-
angular.extend(adapterOnScope, this.publicContext);
80-
this.publicContext = adapterOnScope;
49+
try {
50+
if (ctrlOnData) { // "Controller On", deprecated since v1.6.1
51+
$parse(ctrlOnData.source).assign(ctrlOnData.target, {});
52+
adapterOnScope = $parse(ctrlOnData.source)(ctrlOnData.target);
8153
}
82-
catch (error) {
83-
error.message = `Angular ui-scroll Adapter assignment exception.\n` +
84-
`Can't parse "${$attr.adapter}" expression.\n` +
85-
error.message;
86-
throw error;
54+
else {
55+
$parse(adapterAttr).assign(this.startScope, {});
56+
adapterOnScope = $parse(adapterAttr)(this.startScope);
8757
}
8858
}
59+
catch (error) {
60+
error.message = `Angular ui-scroll Adapter assignment exception.\n` +
61+
`Can't parse "${adapterAttr}" expression.\n` +
62+
error.message;
63+
throw error;
64+
}
65+
66+
angular.extend(adapterOnScope, this.publicContext);
67+
this.publicContext = adapterOnScope;
8968
}
9069

91-
generatePublicContext($attr, $parse, element) {
70+
generatePublicContext($attr, $parse) {
9271
// these methods will be accessible out of ui-scroll via user defined adapter
9372
const publicMethods = ['reload', 'applyUpdates', 'append', 'prepend', 'isBOF', 'isEOF', 'isEmpty'];
9473
for (let i = publicMethods.length - 1; i >= 0; i--) {
@@ -98,19 +77,15 @@ class Adapter {
9877
// these read-only props will be accessible out of ui-scroll via user defined adapter
9978
const publicProps = ['isLoading', 'topVisible', 'topVisibleElement', 'topVisibleScope'];
10079
for (let i = publicProps.length - 1; i >= 0; i--) {
101-
let property, assignProp;
102-
let data = assignAttr($attr[publicProps[i]], this.viewport.getScope(), element);
103-
if (data) {
104-
assignProp = $parse(data.source).assign;
105-
}
80+
let property, attr = $attr[publicProps[i]];
10681
Object.defineProperty(this, publicProps[i], {
10782
get: () => property,
10883
set: (value) => {
10984
property = value;
110-
if (assignProp) {
111-
assignProp(data.target, value);
112-
}
11385
this.publicContext[publicProps[i]] = value;
86+
if (attr) {
87+
$parse(attr).assign(this.startScope, value);
88+
}
11489
}
11590
});
11691
}

src/ui-scroll.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ angular.module('ui.scroll', [])
8181
let elementRoutines = new ElementRoutines($injector, $q);
8282
let buffer = new ScrollBuffer(elementRoutines, bufferSize);
8383
let viewport = new Viewport(elementRoutines, buffer, element, viewportController, $rootScope, padding);
84-
let adapter = new Adapter(viewport, buffer, adjustBuffer, reload, $attr, $parse, element);
84+
let adapter = new Adapter(viewport, buffer, adjustBuffer, reload, $attr, $parse, element, $scope);
8585

8686
if (viewportController) {
8787
viewportController.adapter = adapter;

0 commit comments

Comments
 (0)