spyne 0.18.3 → 0.19.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/spyne.js +4 -3
- package/lib/spyne.min.js +1 -1
- package/lib/spyne.min.js.LICENSE.txt +1 -1
- package/package.json +20 -35
- package/src/spyne/channels/channel-fetch-class.js +4 -2
- package/src/spyne/channels/channel-payload-class.js +8 -7
- package/src/spyne/channels/channel.js +9 -2
- package/src/spyne/channels/channels-map.js +3 -3
- package/src/spyne/channels/spyne-channel-window.js +9 -0
- package/src/spyne/spyne-app.js +2 -2
- package/src/spyne/spyne.js +3 -1
- package/src/spyne/utils/channel-fetch-util.js +16 -6
- package/src/spyne/utils/safe-clone.js +85 -0
- package/src/spyne/utils/spyne-app-properties.js +24 -1
- package/src/spyne/utils/spyne-utils-channel-route-url.js +1 -1
- package/src/spyne/utils/spyne-utils-channel-route.js +1 -2
- package/src/spyne/views/dom-element-template.js +104 -35
- package/src/spyne/views/view-stream-element.js +9 -1
- package/src/spyne/views/view-stream-payload.js +3 -1
- package/src/spyne/views/view-stream-selector.js +24 -5
- package/src/spyne/views/view-stream.js +15 -2
- package/src/tests/channels/channel.test.js +7 -1
- package/src/tests/channels/route-utils.test.js +1 -0
- package/src/tests/utils/channel-data-packet-generator.unused.js +1 -1
- package/src/tests/views/dom-el-template.test.js +18 -1
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
is
|
|
13
13
|
} from 'ramda';
|
|
14
14
|
import {SpyneAppProperties} from '../utils/spyne-app-properties';
|
|
15
|
+
import {safeClone} from '../utils/safe-clone';
|
|
15
16
|
|
|
16
17
|
export class ChannelPayload {
|
|
17
18
|
/**
|
|
@@ -76,15 +77,15 @@ export class ChannelPayload {
|
|
|
76
77
|
|
|
77
78
|
|
|
78
79
|
|
|
79
|
-
channelPayloadItemObj.clone = () =>
|
|
80
|
-
{payload:
|
|
80
|
+
channelPayloadItemObj.clone = () => mergeAll([
|
|
81
|
+
{payload:safeClone(channelPayloadItemObj.payload)},
|
|
81
82
|
channelPayloadItemObj.payload,
|
|
82
|
-
{ channel },
|
|
83
|
-
{ event: event },
|
|
83
|
+
{ channel: clone(channel) },
|
|
84
|
+
{ event: clone(event) },
|
|
84
85
|
{srcElement: srcElement},
|
|
85
|
-
channelPayloadItemObj.srcElement, {
|
|
86
|
-
action: channelPayloadItemObj.action }
|
|
87
|
-
])
|
|
86
|
+
clone(channelPayloadItemObj.srcElement), {
|
|
87
|
+
action: clone(channelPayloadItemObj.action) }
|
|
88
|
+
]);
|
|
88
89
|
|
|
89
90
|
|
|
90
91
|
|
|
@@ -84,7 +84,7 @@ export class Channel {
|
|
|
84
84
|
this.checkForPersistentDataMode = Channel.checkForPersistentDataMode.bind(this);
|
|
85
85
|
this.observer$ = this.props['observer'] = observer$;
|
|
86
86
|
let dispatcherStream$ = this.streamsController.getStream('DISPATCHER');
|
|
87
|
-
const payloadPredByChannelName = propEq(
|
|
87
|
+
const payloadPredByChannelName = propEq(props.name, 'name')
|
|
88
88
|
dispatcherStream$.pipe(filter(payloadPredByChannelName)).subscribe((val) => this.onReceivedObservable(val));
|
|
89
89
|
}
|
|
90
90
|
|
|
@@ -295,7 +295,7 @@ export class Channel {
|
|
|
295
295
|
//console.log("INCOMING ",{action, payload, srcElement}, {obj});
|
|
296
296
|
const mergeProps = (d) => mergeAll([d, { action: prop('action', d) }, prop('payload', d), prop('srcElement', d)]);
|
|
297
297
|
let dataObj = obsVal => ({
|
|
298
|
-
|
|
298
|
+
clone: () => mergeProps(obj.data),
|
|
299
299
|
action, payload, srcElement,
|
|
300
300
|
event: obsVal
|
|
301
301
|
});
|
|
@@ -401,6 +401,13 @@ export class Channel {
|
|
|
401
401
|
}
|
|
402
402
|
|
|
403
403
|
|
|
404
|
+
static checkForNotTrackFlag(props={}){
|
|
405
|
+
if (props.doNotTrack === true){
|
|
406
|
+
SpyneAppProperties.doNotTrackChannel(props.channelName);
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
|
|
410
|
+
}
|
|
404
411
|
|
|
405
412
|
|
|
406
413
|
|
|
@@ -45,8 +45,8 @@ export class ChannelsMap {
|
|
|
45
45
|
|
|
46
46
|
static listRegisteredChannels(showOnlyProxies = false) {
|
|
47
47
|
let proxyMap = this.getChannelsList();
|
|
48
|
-
let rejectProxyFn = reject(propEq('
|
|
49
|
-
let filterProxyFn = filter(propEq('
|
|
48
|
+
let rejectProxyFn = reject(propEq('ChannelProxy', 'val'));
|
|
49
|
+
let filterProxyFn = filter(propEq('ChannelProxy', 'val' ));
|
|
50
50
|
let fn = showOnlyProxies === true ? filterProxyFn : rejectProxyFn;
|
|
51
51
|
let removedProxyArr = fn(proxyMap);
|
|
52
52
|
return pluck(['key'], removedProxyArr);
|
|
@@ -57,7 +57,7 @@ export class ChannelsMap {
|
|
|
57
57
|
|
|
58
58
|
checkForMissingChannels() {
|
|
59
59
|
let proxyMap = this.getChannelsList();
|
|
60
|
-
let filterProxyFn = filter(propEq('
|
|
60
|
+
let filterProxyFn = filter(propEq('ChannelProxy', 'val'));
|
|
61
61
|
let filterProxyArr = filterProxyFn(proxyMap);
|
|
62
62
|
|
|
63
63
|
if (filterProxyArr.length >= 1) {
|
|
@@ -295,9 +295,18 @@ export class SpyneChannelWindow extends Channel {
|
|
|
295
295
|
'CHANNEL_WINDOW_FOCUS_EVENT',
|
|
296
296
|
'CHANNEL_WINDOW_FULLSCREENCHANGE_EVENT',
|
|
297
297
|
'CHANNEL_WINDOW_FULLSCREENERROR_EVENT',
|
|
298
|
+
'CHANNEL_WINDOW_KEYUP_EVENT',
|
|
299
|
+
'CHANNEL_WINDOW_KEYDOWN_EVENT',
|
|
298
300
|
'CHANNEL_WINDOW_LOAD_EVENT',
|
|
299
301
|
'CHANNEL_WINDOW_MEDIA_QUERY_EVENT',
|
|
300
302
|
'CHANNEL_WINDOW_MESSAGE_EVENT',
|
|
303
|
+
'CHANNEL_WINDOW_MOUSEDOWN_EVENT',
|
|
304
|
+
'CHANNEL_WINDOW_MOUSEENTER_EVENT',
|
|
305
|
+
'CHANNEL_WINDOW_MOUSELEAVE_EVENT',
|
|
306
|
+
'CHANNEL_WINDOW_MOUSEMOVE_EVENT',
|
|
307
|
+
'CHANNEL_WINDOW_MOUSEOUT_EVENT',
|
|
308
|
+
'CHANNEL_WINDOW_MOUSEOVER_EVENT',
|
|
309
|
+
'CHANNEL_WINDOW_MOUSEUP_EVENT',
|
|
301
310
|
'CHANNEL_WINDOW_MOUSEWHEEL_EVENT',
|
|
302
311
|
'CHANNEL_WINDOW_OFFLINE_EVENT',
|
|
303
312
|
'CHANNEL_WINDOW_ONLINE_EVENT',
|
package/src/spyne/spyne-app.js
CHANGED
|
@@ -3,7 +3,7 @@ import {ViewStream} from './views/view-stream';
|
|
|
3
3
|
import {SpyneAppProperties} from './utils/spyne-app-properties';
|
|
4
4
|
import {deepMerge} from './utils/deep-merge';
|
|
5
5
|
const _channels = new ChannelsMap();
|
|
6
|
-
const version = '0.
|
|
6
|
+
const version = '0.19.1';
|
|
7
7
|
|
|
8
8
|
class SpyneApplication {
|
|
9
9
|
/**
|
|
@@ -41,7 +41,7 @@ class SpyneApplication {
|
|
|
41
41
|
init(config = {}, testMode=false) {
|
|
42
42
|
//this.channels = new ChannelsMap();
|
|
43
43
|
/*!
|
|
44
|
-
* Spyne 0.
|
|
44
|
+
* Spyne 0.19.1
|
|
45
45
|
* https://spynejs.org
|
|
46
46
|
*
|
|
47
47
|
* @license Copyright 2017-2021, Frank Batista, Relevant Context, LLC. All rights reserved.
|
package/src/spyne/spyne.js
CHANGED
|
@@ -14,6 +14,7 @@ import { ChannelPayload } from './channels/channel-payload-class';
|
|
|
14
14
|
import {ChannelPayloadFilter} from './utils/channel-payload-filter';
|
|
15
15
|
import {SpynePlugin} from './spyne-plugins';
|
|
16
16
|
import { deepMerge } from './utils/deep-merge';
|
|
17
|
+
import {safeClone} from './utils/safe-clone';
|
|
17
18
|
import {SpyneAppProperties} from './utils/spyne-app-properties';
|
|
18
19
|
import {SpyneApp} from './spyne-app';
|
|
19
20
|
|
|
@@ -35,5 +36,6 @@ export {
|
|
|
35
36
|
SpyneApp,
|
|
36
37
|
SpyneAppProperties,
|
|
37
38
|
SpynePlugin,
|
|
38
|
-
deepMerge
|
|
39
|
+
deepMerge,
|
|
40
|
+
safeClone
|
|
39
41
|
};
|
|
@@ -47,7 +47,7 @@ export class ChannelFetchUtil {
|
|
|
47
47
|
*/
|
|
48
48
|
|
|
49
49
|
|
|
50
|
-
constructor(options, subscriber, testMode) {
|
|
50
|
+
constructor(options, subscriber, testMode, CHANNEL_NAME) {
|
|
51
51
|
|
|
52
52
|
const testSubscriber = (p) => console.log('FETCH RETURNED ', p);
|
|
53
53
|
|
|
@@ -57,6 +57,7 @@ export class ChannelFetchUtil {
|
|
|
57
57
|
this._serverOptions = ChannelFetchUtil.setServerOptions(options);
|
|
58
58
|
this._subscriber = subscriber !== undefined ? subscriber : testSubscriber;
|
|
59
59
|
this.debug = options.debug !== undefined ? options.debug : false;
|
|
60
|
+
this.channelName = CHANNEL_NAME;
|
|
60
61
|
|
|
61
62
|
let fetchProps = {
|
|
62
63
|
mapFn: this.mapFn,
|
|
@@ -66,18 +67,27 @@ export class ChannelFetchUtil {
|
|
|
66
67
|
debug: this.debug
|
|
67
68
|
};
|
|
68
69
|
if (testMode !== true) {
|
|
69
|
-
ChannelFetchUtil.startWindowFetch(fetchProps, this._subscriber);
|
|
70
|
+
ChannelFetchUtil.startWindowFetch(fetchProps, this._subscriber, this.channelName);
|
|
70
71
|
}
|
|
71
72
|
}
|
|
72
73
|
|
|
73
|
-
static startWindowFetch(props, subscriber) {
|
|
74
|
+
static startWindowFetch(props, subscriber, channelName) {
|
|
74
75
|
let { mapFn, url, serverOptions, responseType, debug } = props;
|
|
75
|
-
const tapLogDebug = p => console.log('DEBUG FETCH :', p);
|
|
76
|
+
const tapLogDebug = p => console.log('DEBUG FETCH :', p, {url, serverOptions, responseType, channelName});
|
|
76
77
|
const tapLog = debug === true ? tapLogDebug : () => {};
|
|
77
78
|
|
|
79
|
+
const mapWrapper = (mapMethod)=>{
|
|
80
|
+
const metadata = {channelName, url, responseType, serverOptions}
|
|
81
|
+
|
|
82
|
+
return (data)=>{
|
|
83
|
+
return mapMethod(data, metadata);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
}
|
|
87
|
+
|
|
78
88
|
let response$ = from(window.fetch(url, serverOptions))
|
|
79
89
|
.pipe(tap(tapLog), flatMap(r => from(r[responseType]())),
|
|
80
|
-
map(mapFn),
|
|
90
|
+
map(mapWrapper(mapFn)),
|
|
81
91
|
publish());
|
|
82
92
|
|
|
83
93
|
response$.connect();
|
|
@@ -126,7 +136,7 @@ export class ChannelFetchUtil {
|
|
|
126
136
|
|
|
127
137
|
static updateMethodWhenBodyExists(opts) {
|
|
128
138
|
const hasBody = has('body');
|
|
129
|
-
const methodIsGet = propEq('
|
|
139
|
+
const methodIsGet = propEq('GET', 'method');
|
|
130
140
|
const pred = allPass([hasBody, methodIsGet]);
|
|
131
141
|
return when(pred, assoc('method', 'POST'))(opts);
|
|
132
142
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import {clone, compose, fromPairs, is, path, toPairs} from 'ramda';
|
|
2
|
+
import {SpyneAppProperties} from './spyne-app-properties';
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
const getPropType = (prp) => {
|
|
8
|
+
let type = typeof prp;
|
|
9
|
+
if (['number', 'boolean', 'string'].includes(type)){
|
|
10
|
+
type = 'primitive';
|
|
11
|
+
} else if (type==='object'){
|
|
12
|
+
if (Array.isArray(prp)){
|
|
13
|
+
type = 'array'
|
|
14
|
+
} else if (prp===null){
|
|
15
|
+
type = 'undefined';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return type;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
const cmsDataReviveNestedProxyObj = (proxyObj, proxyReviverMethod) => {
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
const {__proxy__proxyName} = proxyObj;
|
|
26
|
+
|
|
27
|
+
if (__proxy__proxyName === undefined){
|
|
28
|
+
console.error('object is not proxy object ',proxyObj);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const cloneNestedProxyObj = (target, pathArr)=>{
|
|
32
|
+
const nestedProxyObj = path(pathArr, proxyObj);
|
|
33
|
+
const {__proxy__isProxy, __proxy__props} = nestedProxyObj;
|
|
34
|
+
return __proxy__isProxy ? proxyReviverMethod(target, __proxy__props) : target;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
const rootObj = cloneNestedProxyObj(clone(proxyObj), []);
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
const proxyIterable = (iterObj, iterPath) => {
|
|
42
|
+
let dataPath = iterPath || [];
|
|
43
|
+
const loopObj = ([key, prop]) => {
|
|
44
|
+
const type = getPropType(prop);
|
|
45
|
+
const clonedPath = [...dataPath]
|
|
46
|
+
clonedPath.push(key);
|
|
47
|
+
if (type === 'object' || type==='array') {
|
|
48
|
+
iterObj[key] = cloneNestedProxyObj(prop, clonedPath);
|
|
49
|
+
proxyIterable(prop, clonedPath)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
Object.entries(iterObj).forEach(loopObj);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
proxyIterable(rootObj);
|
|
56
|
+
// console.timeEnd('proxify2');
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
return rootObj;
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
export const safeClone = function(o){
|
|
68
|
+
const {__proxy__proxyName} = o;
|
|
69
|
+
if (__proxy__proxyName!==undefined){
|
|
70
|
+
const proxyReviverMethod = SpyneAppProperties.getProxyReviver(__proxy__proxyName);
|
|
71
|
+
if (typeof proxyReviverMethod === 'function'){
|
|
72
|
+
return cmsDataReviveNestedProxyObj(o, proxyReviverMethod);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const isArr = is(Array);
|
|
77
|
+
const isObj = is(Object);
|
|
78
|
+
const isIter = ob => isArr(ob)===false && isObj(ob)===true;
|
|
79
|
+
const isIterable = isIter(o);
|
|
80
|
+
return isIterable ? compose(fromPairs, toPairs, clone)(o) : clone(o);
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
}
|
|
@@ -5,9 +5,11 @@ import {path} from 'ramda';
|
|
|
5
5
|
|
|
6
6
|
let _config;
|
|
7
7
|
let _channels;
|
|
8
|
-
let _channelsMap
|
|
8
|
+
let _channelsMap;
|
|
9
9
|
let _initialized = false;
|
|
10
10
|
let _debug = true;
|
|
11
|
+
const _doNotTrackChannelsArr = [];
|
|
12
|
+
const _proxiesMap = new Map();;
|
|
11
13
|
|
|
12
14
|
const _spynePluginMethods = new SpynePluginsMethods();
|
|
13
15
|
|
|
@@ -162,6 +164,27 @@ class SpyneAppPropertiesClass{
|
|
|
162
164
|
|
|
163
165
|
}
|
|
164
166
|
|
|
167
|
+
|
|
168
|
+
|
|
169
|
+
doNotTrackChannel(channelName){
|
|
170
|
+
_doNotTrackChannelsArr.push(channelName);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
getUntrackedChannelsList(){
|
|
174
|
+
return _doNotTrackChannelsArr;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
registerProxyReviver(name, method){
|
|
179
|
+
_proxiesMap.set(name, method);
|
|
180
|
+
//console.log("REGISTERD PROXY REVIVER",_proxiesMap, _proxiesMap.get(name));
|
|
181
|
+
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
getProxyReviver(proxyName){
|
|
185
|
+
return _proxiesMap.get(proxyName);
|
|
186
|
+
}
|
|
187
|
+
|
|
165
188
|
getPluginConfigByPluginName(pluginName){
|
|
166
189
|
return _config.plugins[pluginName];
|
|
167
190
|
}
|
|
@@ -188,7 +188,7 @@ export class SpyneUtilsChannelRouteUrl {
|
|
|
188
188
|
};
|
|
189
189
|
|
|
190
190
|
const checkForEitherStrOrReMatch = either(
|
|
191
|
-
propEq('str'
|
|
191
|
+
propEq(mainStr, 'str'), compose(test(__, mainStr), prop('re'))
|
|
192
192
|
);
|
|
193
193
|
|
|
194
194
|
const findMatchIndex = compose(findLastIndex(equals(true)), map(checkForEitherStrOrReMatch), map(createStrRegexTest), map(checkForEmpty));
|
|
@@ -55,13 +55,12 @@ export class SpyneUtilsChannelRoute {
|
|
|
55
55
|
return obj;
|
|
56
56
|
};
|
|
57
57
|
|
|
58
|
-
const createPred = p => compose(keys, filter(propEq(
|
|
58
|
+
const createPred = p => compose(keys, filter(propEq(true, p)));
|
|
59
59
|
|
|
60
60
|
const getPropsState = compose(map(compareProps), uniq, chain(keys))([obj1, obj2]);
|
|
61
61
|
let pathsChanged = chain(createPred('changed'), getPropsState);
|
|
62
62
|
let pathsAdded = chain(createPred('added'), getPropsState);
|
|
63
63
|
let pathsRemoved = chain(createPred('removed'), getPropsState);
|
|
64
|
-
// console.log("GET KEYS ", pathsChanged);
|
|
65
64
|
obj1 = obj2;
|
|
66
65
|
return { pathsAdded, pathsRemoved, pathsChanged };
|
|
67
66
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import {includes, __, ifElse, path, prop, reject, is, isNil, isEmpty} from 'ramda';
|
|
2
2
|
|
|
3
|
+
|
|
3
4
|
/**
|
|
4
5
|
* @module DomElTemplate
|
|
5
6
|
* @type util
|
|
@@ -133,8 +134,11 @@ import {includes, __, ifElse, path, prop, reject, is, isNil, isEmpty} from 'ramd
|
|
|
133
134
|
*/
|
|
134
135
|
|
|
135
136
|
export class DomElementTemplate {
|
|
136
|
-
constructor(template, data) {
|
|
137
|
+
constructor(template, data={}) {
|
|
137
138
|
this.template = this.formatTemplate(template);
|
|
139
|
+
this.isProxyData = data.__cms__isProxy === true;
|
|
140
|
+
|
|
141
|
+
|
|
138
142
|
|
|
139
143
|
const checkForArrayData = ()=>{
|
|
140
144
|
if (is(Array, data) === true) {
|
|
@@ -149,40 +153,60 @@ export class DomElementTemplate {
|
|
|
149
153
|
|
|
150
154
|
this.templateData = data;
|
|
151
155
|
|
|
152
|
-
|
|
153
156
|
let strArr = DomElementTemplate.getStringArray(this.template);
|
|
154
157
|
|
|
155
|
-
|
|
156
158
|
let strMatches = this.template.match(DomElementTemplate.findTmplLoopsRE());
|
|
157
159
|
strMatches = strMatches === null ? [] : strMatches;
|
|
158
160
|
|
|
159
161
|
const parseTmplLoopsRE = DomElementTemplate.parseTmplLoopsRE();
|
|
162
|
+
|
|
160
163
|
const parseTmplLoopFn = this.parseTheTmplLoop.bind(this);
|
|
161
|
-
const mapTmplLoop = (str, data) => str.replace(parseTmplLoopsRE, parseTmplLoopFn);
|
|
162
|
-
const findTmplLoopsPred = includes(__, strMatches);
|
|
163
164
|
|
|
165
|
+
const mapTmplLoop = (str, data) => {
|
|
166
|
+
return str.replace(parseTmplLoopsRE, parseTmplLoopFn);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const findTmplLoopsPred = includes(__, strMatches);
|
|
164
170
|
const checkForMatches = ifElse(
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
171
|
+
findTmplLoopsPred,
|
|
172
|
+
mapTmplLoop,
|
|
173
|
+
this.addParams.bind(this));
|
|
168
174
|
|
|
169
175
|
this.finalArr = strArr.map(checkForMatches);
|
|
170
176
|
|
|
171
177
|
}
|
|
172
178
|
|
|
179
|
+
static isPrimitiveTag(str){
|
|
180
|
+
return /({{\.\*?}})/.test(str);;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// FIND CORRECT NESTED DATA
|
|
184
|
+
static getNestedDataReducer(data={}, param=""){
|
|
185
|
+
const dataReducer = (nestedData, str) =>{
|
|
186
|
+
if (nestedData[str]){
|
|
187
|
+
return nestedData[str];
|
|
188
|
+
}
|
|
189
|
+
return nestedData;
|
|
190
|
+
}
|
|
191
|
+
return /(\.)/gm.test(String(param)) ? String(param).split('.').reduce(dataReducer,data) : data[param];
|
|
192
|
+
}
|
|
193
|
+
|
|
173
194
|
static getStringArray(template) {
|
|
174
195
|
let strArr = template.split(DomElementTemplate.findTmplLoopsRE());
|
|
175
196
|
const emptyRE = /^([\\n\s\W]+)$/;
|
|
176
197
|
const filterOutEmptyStrings = s => s.match(emptyRE);
|
|
177
|
-
|
|
198
|
+
const finalStr = reject(filterOutEmptyStrings, strArr);
|
|
199
|
+
|
|
200
|
+
return finalStr;
|
|
201
|
+
|
|
178
202
|
}
|
|
179
203
|
|
|
180
204
|
static findTmplLoopsRE() {
|
|
181
|
-
return /({{
|
|
205
|
+
return /({{#[\w.]+}}[\w\n\s\W]+?{{\/[\w.]+}})/gm;
|
|
182
206
|
}
|
|
183
207
|
|
|
184
208
|
static parseTmplLoopsRE() {
|
|
185
|
-
return /({{#(\w+)}})([\w\n\s\W]+?)({{\/\2}})/gm;
|
|
209
|
+
return /({{#([\w.]+)}})([\w\n\s\W]+?)({{\/\2}})/gm;
|
|
186
210
|
}
|
|
187
211
|
|
|
188
212
|
static swapParamsForTagsRE() {
|
|
@@ -196,10 +220,10 @@ export class DomElementTemplate {
|
|
|
196
220
|
}
|
|
197
221
|
|
|
198
222
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
223
|
+
/**
|
|
224
|
+
*
|
|
225
|
+
* @desc Returns a document fragment generated from the template and any added data.
|
|
226
|
+
*/
|
|
203
227
|
|
|
204
228
|
|
|
205
229
|
renderDocFrag() {
|
|
@@ -207,7 +231,7 @@ export class DomElementTemplate {
|
|
|
207
231
|
const isTableSubTag = /^([^>]*?)(<){1}(\b)(thead|col|colgroup|tbody|td|tfoot|tr|th)(\b)([^\0]*)$/.test(html);
|
|
208
232
|
const el = isTableSubTag ? html : document.createRange().createContextualFragment(html);
|
|
209
233
|
|
|
210
|
-
|
|
234
|
+
window.setTimeout(this.removeThis(), 2);
|
|
211
235
|
return el;
|
|
212
236
|
|
|
213
237
|
}
|
|
@@ -233,52 +257,97 @@ export class DomElementTemplate {
|
|
|
233
257
|
}
|
|
234
258
|
|
|
235
259
|
addParams(str) {
|
|
236
|
-
//console.time(this.tempL+'9')
|
|
237
260
|
const re = /(\.)/gm;
|
|
238
|
-
|
|
239
261
|
const replaceTags = (str, p1, p2, p3) => {
|
|
240
|
-
|
|
241
|
-
return this.templateData[p2];
|
|
242
|
-
}
|
|
243
|
-
return this.getDataValFromPathStr(p2, this.templateData);
|
|
262
|
+
return DomElementTemplate.getNestedDataReducer(this.templateData, p2);
|
|
244
263
|
};
|
|
245
|
-
|
|
246
|
-
return str.replace(DomElementTemplate.swapParamsForTagsRE(), replaceTags);
|
|
264
|
+
return str.replace(DomElementTemplate.swapParamsForTagsRE(), replaceTags);
|
|
247
265
|
|
|
248
266
|
}
|
|
249
267
|
|
|
250
|
-
parseTheTmplLoop(str, p1, p2, p3) {
|
|
251
268
|
|
|
252
|
-
|
|
269
|
+
|
|
270
|
+
|
|
271
|
+
parseTheTmplLoop(str, p1, p2, p3) {
|
|
272
|
+
const dotConverter = str=>`${str.replace(/(\.)/g, "][")}`
|
|
253
273
|
const reDot = /(\.)/gm;
|
|
254
274
|
const subStr = p3;
|
|
255
|
-
|
|
256
|
-
const
|
|
275
|
+
|
|
276
|
+
const dataReducer = (acc, str) =>{
|
|
277
|
+
acc = acc[str];
|
|
278
|
+
return acc;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
|
|
282
|
+
let elData = DomElementTemplate.getNestedDataReducer(this.templateData, p2);
|
|
283
|
+
|
|
284
|
+
const arrayStringToObjAdapter = (d,str, i)=>{
|
|
285
|
+
|
|
286
|
+
// IF {{.}} RUN parseString
|
|
287
|
+
if (DomElementTemplate.isPrimitiveTag(str)){
|
|
288
|
+
return parseString(d, str, i);
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
// CREATE DATA OBJ -- CHECK TO ADD PROXY VALUES
|
|
292
|
+
const createDataObj = ()=>{
|
|
293
|
+
const spyneLoopKey = d;
|
|
294
|
+
const loopIndex = i;
|
|
295
|
+
const loopNum = i+1;
|
|
296
|
+
|
|
297
|
+
if (this.isProxyData) {
|
|
298
|
+
const __cms__dataId = elData.__cms__dataId;
|
|
299
|
+
const keyIdStr = `__cms__keyFor_${d}`
|
|
300
|
+
const origKey = elData[keyIdStr];
|
|
301
|
+
return {spyneLoopKey, __cms__dataId, origKey, loopIndex, loopNum, d}
|
|
302
|
+
|
|
303
|
+
}
|
|
304
|
+
return {spyneLoopKey, loopIndex, loopNum};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return parseObject(createDataObj(), str, i);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
const parseString = (item, str, index, origIndex) => {
|
|
257
311
|
return str.replace(DomElementTemplate.swapParamsForTagsRE(), item);
|
|
258
312
|
};
|
|
259
|
-
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
// PARSING ARRAYS AND OBJECTS
|
|
316
|
+
const parseObject = (obj, str, i) => {
|
|
317
|
+
/// LOOP NUMBER VALUES AUTO ADDED
|
|
318
|
+
|
|
319
|
+
//const loopIndex = i;
|
|
320
|
+
//const loopNum = i+1;
|
|
321
|
+
|
|
260
322
|
const loopObj = (str, p1, p2) => {
|
|
261
323
|
// DOT SYNTAX CHECK
|
|
324
|
+
const hash = {
|
|
325
|
+
loopIndex: i,
|
|
326
|
+
loopNum: i+1
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
// IF {{.}}
|
|
262
330
|
if (reDot.test(p2) === false && obj[p2] !==undefined) {
|
|
263
|
-
return obj[p2]
|
|
331
|
+
return hash[p2] !== undefined ? hash[p2] : obj[p2]
|
|
264
332
|
}
|
|
265
333
|
|
|
266
|
-
|
|
334
|
+
const dataReducedVal = this.getDataValFromPathStr(p2, obj);
|
|
335
|
+
return hash[p2] !== undefined ? hash[p2] : dataReducedVal
|
|
267
336
|
};
|
|
268
337
|
return str.replace(DomElementTemplate.swapParamsForTagsRE(), loopObj);
|
|
269
338
|
};
|
|
270
|
-
const mapStringData = (d) => typeof(d) === 'string' ? parseString(d, subStr) : parseObject(d, subStr);
|
|
271
339
|
|
|
340
|
+
const mapStringData = (d, i) => typeof(d) === 'string' ? arrayStringToObjAdapter(d, subStr, i) : parseObject(d, subStr, i);
|
|
272
341
|
|
|
273
342
|
if (isNil(elData) === true || isEmpty(elData)) {
|
|
274
343
|
return '';
|
|
275
344
|
}
|
|
276
345
|
|
|
277
346
|
if (elData.length===undefined) {
|
|
278
|
-
|
|
279
|
-
|
|
347
|
+
elData = [elData];
|
|
348
|
+
}
|
|
280
349
|
|
|
281
|
-
|
|
350
|
+
return elData.map(mapStringData).join('');
|
|
282
351
|
|
|
283
352
|
|
|
284
353
|
}
|
|
@@ -155,9 +155,17 @@ export class ViewStreamElement {
|
|
|
155
155
|
let container = isNil(d.query) ? d.node : d.query;
|
|
156
156
|
let prepend = (node, item) => node.insertBefore(item, node.firstChild);
|
|
157
157
|
let append = (node, item) => node.appendChild(item);
|
|
158
|
+
let after = (node, item) => node.after(item);
|
|
159
|
+
|
|
160
|
+
const defaultFn = prepend;
|
|
161
|
+
const attachTypeHash = {
|
|
162
|
+
'appendChild' : append,
|
|
163
|
+
'after' : after
|
|
164
|
+
}
|
|
158
165
|
// DETERMINE WHETHER TO USE APPEND OR PREPEND
|
|
159
166
|
// ON CONNECTING DOM ITEMS TO EACH OTHER
|
|
160
|
-
let attachFunc = d.attachType === 'appendChild' ? append : prepend;
|
|
167
|
+
//let attachFunc = d.attachType === 'appendChild' ? append : prepend;
|
|
168
|
+
const attachFunc = attachTypeHash[d.attachType] || defaultFn;
|
|
161
169
|
attachFunc(container, this.domItem.render());
|
|
162
170
|
this.setAnimateIn(d);
|
|
163
171
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import {SpyneAppProperties} from '../utils/spyne-app-properties';
|
|
2
|
+
import {safeClone} from '../utils/safe-clone';
|
|
2
3
|
import { gc } from '../utils/gc';
|
|
3
4
|
import {
|
|
4
5
|
compose,
|
|
@@ -36,7 +37,8 @@ export class ViewStreamPayload {
|
|
|
36
37
|
|
|
37
38
|
sendToDirectorStream(payload) {
|
|
38
39
|
let directorStream$ = SpyneAppProperties.channelsMap.getStream('DISPATCHER');
|
|
39
|
-
const frozenPayload =
|
|
40
|
+
const frozenPayload = safeClone(payload);
|
|
41
|
+
//console.log("VS PAYLOAD ",frozenPayload);
|
|
40
42
|
directorStream$.next(frozenPayload);
|
|
41
43
|
payload = undefined;
|
|
42
44
|
|
|
@@ -33,7 +33,7 @@ function testSelectors(cxt, str, verboseBool) {
|
|
|
33
33
|
const elIsDomElement = compose(lte(0), defaultTo(-1),
|
|
34
34
|
prop('nodeType'));
|
|
35
35
|
|
|
36
|
-
if (elIsDomElement(el) === false) {
|
|
36
|
+
if (el !== null && elIsDomElement(el) === false) {
|
|
37
37
|
console.warn(`Spyne Warning: the el object is not a valid single element, ${el}`);
|
|
38
38
|
return;
|
|
39
39
|
}
|
|
@@ -52,18 +52,37 @@ function testSelectors(cxt, str, verboseBool) {
|
|
|
52
52
|
|
|
53
53
|
function getNodeListArray(cxt, str, verboseBool=false) {
|
|
54
54
|
let selector = str !== undefined ? `${cxt} ${str}` : cxt;
|
|
55
|
+
let isParent = false;
|
|
55
56
|
|
|
56
57
|
|
|
57
58
|
const returnSelectorIfValid = (selector) => {
|
|
58
|
-
|
|
59
|
-
|
|
59
|
+
let arr = [];
|
|
60
|
+
try {
|
|
61
|
+
arr = document.querySelectorAll(selector)
|
|
62
|
+
} catch (e) { arr = [] }
|
|
63
|
+
try {
|
|
64
|
+
isParent = document.querySelector(str) === document.querySelector(cxt);
|
|
65
|
+
if (isParent === true){
|
|
66
|
+
arr = [document.querySelector(str)];
|
|
67
|
+
}
|
|
68
|
+
} catch(e){
|
|
69
|
+
//return [];
|
|
70
|
+
}
|
|
71
|
+
return arr;// document.querySelectorAll(selector);
|
|
60
72
|
};
|
|
61
73
|
|
|
62
74
|
|
|
75
|
+
const elArr = returnSelectorIfValid(selector);
|
|
76
|
+
|
|
63
77
|
if (verboseBool===true) {
|
|
64
|
-
|
|
78
|
+
const mainSel = isParent === true ? 'body' : cxt;
|
|
79
|
+
testSelectors(mainSel, str, verboseBool);
|
|
65
80
|
}
|
|
66
|
-
|
|
81
|
+
|
|
82
|
+
return elArr;
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
|
|
67
86
|
}
|
|
68
87
|
|
|
69
88
|
function setInlineCss(val, cxt, str) {
|