Skip to content

Commit 22a209e

Browse files
committed
v2.93.0-RC4
+ default [root-route] for the SPA root (/) + Enhancements to work with other Frameworks like React and OJet. + Minor code cleanup
1 parent e2ce864 commit 22a209e

File tree

6 files changed

+152
-82
lines changed

6 files changed

+152
-82
lines changed

bower.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"description": "Single Page Application (SPA) Simplified Framework/Library",
44
"main": "dist/spa-bundle.js",
55

6-
"version": "2.93.0-RC2",
6+
"version": "2.93.0-RC4",
77
"license": "MIT",
88
"homepage": "https://github.com/sucom/SPA.js",
99

dist/spa-bundle.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/spa-bundle.slim.min.js

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "spa.js",
3-
"version": "2.93.0-RC2",
3+
"version": "2.93.0-RC4",
44
"description": "Single Page Application (SPA) Simplified Framework/Library",
55
"main": "dist/spa-bundle.js",
66
"repository": {

src/spa.js

Lines changed: 145 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
(function() {
3535

36-
var _VERSION = '2.93.0-RC3';
36+
var _VERSION = '2.93.0-RC4';
3737
var _version = _VERSION+'-'+(_now('.'));
3838

3939
/* Establish the win object, 'window' in the browser */
@@ -6294,67 +6294,28 @@
62946294
}
62956295
}
62966296

6297-
xsr.renderComponentsInHtml = function (scope, pComponentName, renderSelf) {
6298-
6299-
(scope && (typeof scope === 'object') && scope.length && !scope[0] && (scope = ''));
6297+
function _parseAndRenderDomForSpaElements (scope, force) {
6298+
if (_isBool(scope)) {
6299+
force = scope;
6300+
scope = '';
6301+
}
63006302
scope = scope||'body';
63016303

6302-
renderOptions = (typeof pComponentName == 'object')? pComponentName : '';
6303-
pComponentName = (typeof pComponentName == 'string')? pComponentName.trim() : '';
6304-
6305-
var $spaCompList = $(scope);
6306-
var retVal;
6307-
6308-
if (!renderSelf) {
6309-
/*Register Events *for* in a, button, form elements */
6310-
_registerEventsForComponentRender(scope);
6311-
6312-
// <spa-template src=""> <x-template src="">
6313-
var templateTags = _spaTagsSelector('spa-template,x-template');
6314-
$(scope).find(templateTags).each(function(){
6315-
// _attr(this, 'data-spa-component', _attr(this,'src'));
6316-
_attr(this, 'data-x-component', _attr(this,'src'));
6317-
_attr(this, 'data-skip-data-bind', 'true');
6318-
_attr(this, 'data-template-script', 'true');
6319-
this.style.display = 'none';
6320-
});
6321-
6322-
// <spa-html src=""> <x-html src=""> with optional [data] attribute
6323-
var htmlTags = _spaTagsSelector('spa-html,x-html');
6324-
$(scope).find(htmlTags).each(function(){
6325-
var htmlSrc = _attr(this,'src');
6326-
var isSpaComponent = ((htmlSrc[0] === '$') || !(/[^a-z0-9]/ig).test( htmlSrc ));
6327-
if (isSpaComponent && !xsr.components[htmlSrc.replace(/[^a-z0-9]/gi,'_')]) {
6328-
var cOptions = {
6329-
templateScript: true
6330-
};
6331-
var skipDataBind = (!(this.hasAttribute('data') || this.hasAttribute('data-url')));
6332-
if (skipDataBind) {
6333-
cOptions['skipDataBind'] = true;
6334-
} else if (!this.hasAttribute('data-url')) {
6335-
cOptions['data'] = this.hasAttribute('data')? _toObj(_attr(this,'data')) : {};
6336-
}
6337-
xsr.$(htmlSrc, cOptions);
6338-
}
6339-
// _attr(this, 'data-spa-component', htmlSrc);
6340-
_attr(this, 'data-x-component', htmlSrc);
6341-
});
6304+
$spaCompList = _getSpa$Elements(scope, !force);
63426305

6343-
// <spa-component src=""> <x-component src="">
6344-
var componentTags = _spaTagsSelector('spa-component,x-component');
6345-
$(scope).find(componentTags).each(function(){
6346-
// _attr(this, 'data-spa-component', _attr(this,'src'));
6347-
_attr(this, 'data-x-component', _attr(this,'src'));
6348-
});
6306+
return _renderSpaDomElements($spaCompList);
6307+
}
6308+
xsr.refresh = _parseAndRenderDomForSpaElements;
6309+
xsr.refreshAll = xsr.renderAll = function (scope) {
6310+
return _parseAndRenderDomForSpaElements(scope, true);
6311+
};
63496312

6350-
// other [src]
6351-
var altCompSelector = ('[src]'+('audio embed iframe img input script source track video x-script [data-x-component] [data-spa-component]'
6352-
.split(' ').map(function(tag){ return ':not('+tag+')'; }).join('')));
6353-
$(scope).find(altCompSelector).each(function(){
6354-
_attr(this, 'data-x-component', _attr(this,'src'));
6355-
});
6313+
function _renderSpaDomElements ($spaCompList, pComponentName, renderOptions) {
6314+
var retVal;
63566315

6357-
$spaCompList = $spaCompList.find('[data-x-component],[data-spa-component]').filter(':not([render-after])');
6316+
if (arguments.length==1) {
6317+
pComponentName = '';
6318+
renderOptions = {};
63586319
}
63596320

63606321
if ($spaCompList.length){
@@ -6458,6 +6419,84 @@
64586419
}
64596420

64606421
return retVal;
6422+
}
6423+
6424+
function _prepareSpaElements (scope) {
6425+
/*Register Events *for* in a, button, form elements */
6426+
_registerEventsForComponentRender(scope);
6427+
6428+
// <spa-template src=""> <x-template src="">
6429+
var templateTags = _spaTagsSelector('spa-template,x-template');
6430+
$(scope).find(templateTags).each(function(){
6431+
// _attr(this, 'data-spa-component', _attr(this,'src'));
6432+
_attr(this, 'data-x-component', _attr(this,'src'));
6433+
_attr(this, 'data-skip-data-bind', 'true');
6434+
_attr(this, 'data-template-script', 'true');
6435+
this.style.display = 'none';
6436+
});
6437+
6438+
// <spa-html src=""> <x-html src=""> with optional [data] attribute
6439+
var htmlTags = _spaTagsSelector('spa-html,x-html');
6440+
$(scope).find(htmlTags).each(function(){
6441+
var htmlSrc = _attr(this,'src');
6442+
var isSpaComponent = ((htmlSrc[0] === '$') || !(/[^a-z0-9]/ig).test( htmlSrc ));
6443+
if (isSpaComponent && !xsr.components[htmlSrc.replace(/[^a-z0-9]/gi,'_')]) {
6444+
var cOptions = {
6445+
templateScript: true
6446+
};
6447+
var skipDataBind = (!(this.hasAttribute('data') || this.hasAttribute('data-url')));
6448+
if (skipDataBind) {
6449+
cOptions['skipDataBind'] = true;
6450+
} else if (!this.hasAttribute('data-url')) {
6451+
cOptions['data'] = this.hasAttribute('data')? _toObj(_attr(this,'data')) : {};
6452+
}
6453+
xsr.$(htmlSrc, cOptions);
6454+
}
6455+
// _attr(this, 'data-spa-component', htmlSrc);
6456+
_attr(this, 'data-x-component', htmlSrc);
6457+
});
6458+
6459+
// <spa-component src=""> <x-component src="">
6460+
var componentTags = _spaTagsSelector('spa-component,x-component');
6461+
$(scope).find(componentTags).find(':not([data-x-component])').each(function(){
6462+
// _attr(this, 'data-spa-component', _attr(this,'src'));
6463+
_attr(this, 'data-x-component', _attr(this,'src'));
6464+
});
6465+
6466+
// other [src]
6467+
var altCompSelector = ('[src]'+('audio embed iframe img input script source track video x-script [data-x-component] [data-spa-component]'
6468+
.split(' ').map(function(tag){ return ':not('+tag+')'; }).join('')));
6469+
$(scope).find(altCompSelector).each(function(){
6470+
_attr(this, 'data-x-component', _attr(this,'src'));
6471+
});
6472+
}
6473+
6474+
function _getSpa$Elements (scope, forMissedOnly) {
6475+
_prepareSpaElements(scope);
6476+
6477+
var $spaCompList = $(scope);
6478+
var forMissed = forMissedOnly? ':not([data-rendered-component])' : '';
6479+
6480+
$spaCompList = $spaCompList.find('[data-x-component],[data-spa-component]').filter(':not([render-after])'+forMissed);
6481+
6482+
return $spaCompList;
6483+
}
6484+
6485+
xsr.renderComponentsInHtml = function (scope, pComponentName, renderSelf) {
6486+
6487+
(scope && (typeof scope === 'object') && scope.length && !scope[0] && (scope = ''));
6488+
scope = scope||'body';
6489+
6490+
renderOptions = (typeof pComponentName == 'object')? pComponentName : '';
6491+
pComponentName = (typeof pComponentName == 'string')? pComponentName.trim() : '';
6492+
6493+
var $spaCompList = $(scope);
6494+
6495+
if (!renderSelf) {
6496+
$spaCompList = _getSpa$Elements(scope);
6497+
}
6498+
6499+
return _renderSpaDomElements($spaCompList, pComponentName, renderOptions);
64616500
};
64626501

64636502
xsr.renderUtils = {
@@ -6822,7 +6861,12 @@
68226861
xsr.render = function (viewContainerId, uOptions) {
68236862
_log.log('xsr.render', viewContainerId, uOptions);
68246863

6825-
if (!arguments.length) return;
6864+
if ((!arguments.length) ||
6865+
(_isBool(viewContainerId)) ||
6866+
(_isBool(uOptions)) ||
6867+
(_isStr(viewContainerId) && !/^#/.test(viewContainerId.trim()) && !_isObj(uOptions))) {
6868+
return _parseAndRenderDomForSpaElements.apply(xsr, ([]).slice.call(arguments));
6869+
}
68266870

68276871
//render with single argument with target
68286872
if ((arguments.length===1) && (typeof viewContainerId === "object")) {
@@ -10457,34 +10501,40 @@
1045710501

1045810502

1045910503
var _isInReact;
10504+
var _isInReactSet;
1046010505
var _isInOjEnv;
10506+
var _isInOjEnvSet;
10507+
var _isAMDenv;
1046110508
var _isInExtEnv;
1046210509

1046310510
function _checkExtEnv () {
10464-
if (!_isInExtEnv) {
10465-
_isInReact = win.__reactRefreshInjected;
10466-
_isInOjEnv = (win['oj'] && _spa_hasPrimaryKeys(oj, 'version&revision&Model&Router'));
10467-
_isInExtEnv = _isInReact || _isInOjEnv;
10511+
_log.log('Checking external environments ...');
1046810512

10469-
if (_isInExtEnv) {
10513+
_isAMDenv = !!(win['require'] && win['define']);
10514+
_isInReact = !!win['__reactRefreshInjected'];
10515+
_isInOjEnv = !!(win['oj'] && _spa_hasPrimaryKeys(oj, 'version&revision&Model&Router'));
10516+
_isInExtEnv = _isInReact || _isInOjEnv || _isAMDenv;
10517+
_log.log('🚀 ~ _isInExtEnv:',_isInExtEnv,' _isInReact:',_isInReact,' _isInOjEnv:',_isInOjEnv,' _isAMDenv:',_isAMDenv);
1047010518

10471-
if (_isInReact) {
10472-
(_isLocEnv && console.info('Found SPA in React env! Setting default SPA-components folder to "public/components" instead of "app/components". NOTE: This message will not appear in production env.'));
10473-
xsr.defaults.components.rootPath = 'components/';
10474-
}
10519+
if (_isInExtEnv) {
1047510520

10476-
if (_isInOjEnv) {
10477-
(_isLocEnv && console.info('Found SPA in OJet env! Setting default SPA-components folder to "src/js/components" instead of "app/components". NOTE: This message will not appear in production env.'));
10478-
xsr.defaults.components.rootPath = 'js/components/';
10479-
}
10521+
if (_isInReact && !_isInReactSet) {
10522+
(_isLocEnv && console.info('Found SPA in React env! Setting default SPA-components folder to "public/components" instead of "app/components". NOTE: This message will not appear in production env.'));
10523+
xsr.defaults.components.rootPath = 'components/';
10524+
_isInReactSet=true;
10525+
}
1048010526

10527+
if (_isInOjEnv && !_isInOjEnvSet) {
10528+
(_isLocEnv && console.info('Found SPA in OJet env! Setting default SPA-components folder to "src/js/components" instead of "app/components". NOTE: This message will not appear in production env.'));
10529+
xsr.defaults.components.rootPath = 'js/components/';
10530+
_isInOjEnvSet = true;
1048110531
}
1048210532

1048310533
observeDOM();
1048410534
}
1048510535
}
1048610536

10487-
function _initSpaDefaults(){
10537+
function _initSpaDefaults(cfgObj){
1048810538
var defaultsInTag
1048910539
, $body = $('body')
1049010540
, elBody = $body[0]
@@ -10515,6 +10565,10 @@
1051510565
win[xsr.defaults.alias] = xsr;
1051610566
}
1051710567

10568+
if (cfgObj && _isObj(cfgObj)) {
10569+
xsr.defaults.set(cfgObj);
10570+
}
10571+
1051810572
_initRoutesDefaults(); //run_once
1051910573
_initApiUrls(); //need to run on 1st Component renderCallback as well
1052010574
}
@@ -10591,7 +10645,20 @@
1059110645
}
1059210646

1059310647
var domObserver;
10594-
function onDomChange(mutationsList) {
10648+
var stoRenderMissingEl;
10649+
function deferLookupOnDomChange () {
10650+
_log.log('deferring scan for SPA elements to render on DOM change.');
10651+
clearTimeout(stoRenderMissingEl);
10652+
stoRenderMissingEl = setTimeout(function() {
10653+
if (_isRendering()) {
10654+
deferLookupOnDomChange();
10655+
} else {
10656+
_log.log('looking for SPA elements to render on DOM Change ...');
10657+
_parseAndRenderDomForSpaElements();
10658+
}
10659+
},200);
10660+
}
10661+
function onDomChange(mutationsList) {
1059510662
if (!_isRendering() && !stoRender) {
1059610663
var pContainer, mutation;
1059710664
for(var i=0; i<mutationsList.length; i++) {
@@ -10602,6 +10669,7 @@
1060210669
break;
1060310670
}
1060410671
}
10672+
1060510673
if (pContainer) {
1060610674
var pContainerId = pContainer.id || (pContainer.tagName+'-'+(_rand(1000, 9999))+'-'+_now());
1060710675
pContainer.id = pContainerId;
@@ -10611,6 +10679,8 @@
1061110679
}, 1, '#'+pContainerId);
1061210680
_log.log('DOM watch: New element(s) added inside Non-SPA component container', pContainer);
1061310681
}
10682+
} else {
10683+
deferLookupOnDomChange();
1061410684
}
1061510685
}
1061610686
function observeDOM () {
@@ -10649,7 +10719,7 @@
1064910719
_cInfoMsg('Failed to self start SPA! In an external environment, start SPA using spa.start() when all modules are loaded.');
1065010720
}
1065110721
}
10652-
function _beginSPA(){
10722+
function _beginSPA(cfgObj){
1065310723
_log.log('begin SPA');
1065410724

1065510725
if (!isSPAReady) _initXHR();
@@ -10660,7 +10730,7 @@
1066010730
if (xhrLib) {
1066110731

1066210732
//Read xsr.defaults from body
10663-
_initSpaDefaults();
10733+
_initSpaDefaults(cfgObj);
1066410734

1066510735
/* ajaxPrefilter */
1066610736
$ajaxPrefilter(_ajaxPrefilter);

src/spa.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)