Improve scripts load system

This commit is contained in:
RainLoop Team 2016-05-20 03:04:15 +03:00
parent 58b9eed8e8
commit 72bf212f67
39 changed files with 916 additions and 411 deletions

View file

@ -23,7 +23,7 @@ class AbstractApp extends AbstractBoot
{
super();
this.iframe = $('<iframe style="display:none" src="javascript:;" />').appendTo('body');
this.iframe = $('<iframe style="display:none" />').appendTo('body');
Globals.$win.on('error', function (oEvent) {
if (oEvent && oEvent.originalEvent && oEvent.originalEvent.message &&

View file

@ -1213,13 +1213,6 @@ class AppUser extends AbstractApp
{
kn.hideLoading();
progressJs.onbeforeend(() => {
$('.progressjs-container').hide();
_.delay(() => {
$('.progressjs-container').remove();
}, 100);
});
progressJs.set(100).end();
}
else
@ -1239,7 +1232,6 @@ class AppUser extends AbstractApp
require('Stores/User/Contact').populate();
var
$LAB = require('$LAB'),
sJsHash = Settings.appSettingsGet('jsHash'),
sStartupUrl = Utils.pString(Settings.settingsGet('StartupUrl')),
iContactsSyncInterval = Utils.pInt(Settings.settingsGet('ContactsSyncInterval')),
@ -1288,7 +1280,7 @@ class AppUser extends AbstractApp
kn.routeOn();
}
if ($LAB && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP))
if (window.jsloader && window.crypto && window.crypto.getRandomValues && Settings.capa(Enums.Capa.OpenPGP))
{
const openpgpCallback = (openpgp) => {
@ -1298,8 +1290,7 @@ class AppUser extends AbstractApp
{
try
{
// PgpStore.openpgp.initWorker(Links.openPgpWorkerJs()); // 1.2.0
PgpStore.openpgp.initWorker({path: Links.openPgpWorkerJs()}); // 2.3.0
PgpStore.openpgp.initWorker({path: Links.openPgpWorkerJs()});
}
catch (e)
{
@ -1321,7 +1312,7 @@ class AppUser extends AbstractApp
}
else
{
$LAB.script(Links.openPgpJs()).wait(() => {
window.jsloader(Links.openPgpJs()).then(() => {
if (window.openpgp)
{
openpgpCallback(window.openpgp);

View file

@ -1,13 +1,20 @@
import window from 'window';
import $ from '$';
import progressJs from 'progressJs';
import rainLoopStorage from 'Storage/RainLoop';
let rlAppDataStorage = null;
window.__rlah = () => {
return rainLoopStorage ? rainLoopStorage.getHash() : null;
};
window.__rlah_data = () => {
return rlAppDataStorage;
};
window.__rlah_set = () => {
if (rainLoopStorage)
{
@ -22,20 +29,59 @@ window.__rlah_clear = () => {
}
};
window.__includeScr = (src) => {
window.document.write(unescape('%3Csc' + 'ript data-cfasync="false" type="text/jav' + 'ascr' + 'ipt" sr' + 'c="' + src + '"%3E%3C/' + 'scr' + 'ipt%3E'));
};
window.__includeAppScr = (src) => {
window.__includeScr(src + (window.__rlah ? window.__rlah() || '0' : '0') + '/' + window.Math.random().toString().substr(2) + '/');
};
window.__includeStyle = (styles) => {
function includeStyle(styles)
{
window.document.write(unescape('%3Csty' + 'le%3E' + styles + '"%3E%3C/' + 'sty' + 'le%3E'));
};
}
window.__showError = (additionalError) => {
function includeScr(src)
{
window.document.write(unescape('%3Csc' + 'ript type="text/jav' + 'ascr' + 'ipt" data-cfasync="false" sr' + 'c="' + src + '"%3E%3C/' + 'scr' + 'ipt%3E'));
}
function includeLayout()
{
const
layout = require('Html/Layout.html'),
app = window.document.getElementById('rl-app')
;
if (app && layout)
{
app.innerHTML = layout.replace(/[\r\n\t]+/g, '');
return true;
}
return false;
}
function includeAppScr(data = {})
{
let src = './?/';
src += data.admin ? 'Admin' : '';
src += 'AppData@';
src += data.mobile ? 'mobile' : 'no-mobile';
src += data.mobileDevice ? '-1' : '-0';
src += '/';
includeScr(src + (window.__rlah ? window.__rlah() || '0' : '0') + '/' + window.Math.random().toString().substr(2) + '/');
}
function getRainloopBootData()
{
let result = {};
const meta = window.document.getElementById('app-boot-data');
if (meta && meta.getAttribute)
{
result = JSON.parse(meta.getAttribute('content')) || {};
}
return result;
}
function showError(additionalError)
{
const
oR = window.document.getElementById('rl-loading'),
oL = window.document.getElementById('rl-loading-error'),
@ -58,14 +104,14 @@ window.__showError = (additionalError) => {
oLA.innerHTML = additionalError;
}
if (window.rainloopProgressJs)
if (progressJs)
{
window.rainloopProgressJs.set(100);
progressJs.set(100).end();
}
}
};
window.__showDescription = (description) => {
function showDescriptionAndLoading(description)
{
const
oE = window.document.getElementById('rl-loading'),
oElDesc = window.document.getElementById('rl-loading-desc')
@ -83,76 +129,81 @@ window.__showDescription = (description) => {
oE.style.opacity = 1;
}, 300);
}
};
}
window.__runBoot = (withError, additionalError) => {
if (window.__APP_BOOT && !withError) {
function runMainBoot(withError, additionalError)
{
if (window.__APP_BOOT && !withError)
{
window.__APP_BOOT(function (bV) {
if (!bV) {
window.__showError(additionalError);
if (!bV)
{
showError(additionalError);
}
});
} else {
window.__showError(additionalError);
}
};
window.__runApp = (BaseAppLibsScriptLink, BaseAppMainScriptLink, BaseAppEditorScriptLink) => {
const appData = window.rainloopAppData;
if (window.$LAB && window.progressJs && appData && appData.TemplatesLink && appData.LangLink)
else
{
const p = window.progressJs();
window.rainloopProgressJs = p;
showError(additionalError);
}
}
function runApp()
{
const appData = window.__rlah_data();
if (window.jsloader && progressJs && appData && appData.TemplatesLink && appData.LangLink &&
appData.StaticLibJsLink && appData.StaticAppJsLink && appData.StaticEditorJsLink)
{
const p = progressJs;
p.setOptions({theme: 'rainloop'});
p.start().set(5);
window.$LAB
.script(function () {
return [
{src: BaseAppLibsScriptLink, type: 'text/javascript', charset: 'utf-8'}
];
})
.wait(function () {
const
libs = window.jsloader(appData.StaticLibJsLink).then(() => {
if (window.$)
{
if (!window.$('#rl-check').is(':visible'))
{
window.$('html').addClass('no-css');
throw new Error('no-css');
}
p.set(20);
window.$('#rl-check').remove();
if (appData.IncludeBackground && $) {
$('#rl-bg').attr('style', 'background-image: none !important;')
if (appData.IncludeBackground)
{
window.$('#rl-bg').attr('style', 'background-image: none !important;')
.backstretch(appData.IncludeBackground.replace('{{USER}}',
(window.__rlah ? window.__rlah() || '0' : '0')), {fade: 100, centeredX: true, centeredY: true})
(window.__rlah ? (window.__rlah() || '0') : '0')), {fade: 100, centeredX: true, centeredY: true})
.removeAttr('style')
;
}
})
.script(function () {
return [
{src: appData.TemplatesLink, type: 'text/javascript', charset: 'utf-8'},
{src: appData.LangLink, type: 'text/javascript', charset: 'utf-8'}
];
})
.wait(function () {
}
}),
common = window.Promise.all([
window.jsloader(appData.TemplatesLink),
window.jsloader(appData.LangLink)
])
;
window.Promise.all([libs, common])
.then(() => {
p.set(30);
})
.script(function () {
return {src: BaseAppMainScriptLink, type: 'text/javascript', charset: 'utf-8'};
})
.wait(function () {
return window.jsloader(appData.StaticAppJsLink);
}).then(() => {
p.set(50);
})
.script(function () {
return appData.PluginsLink ? {src: appData.PluginsLink, type: 'text/javascript', charset: 'utf-8'} : null;
})
.wait(function () {
return appData.PluginsLink ? window.jsloader(appData.PluginsLink) : window.Promise.resolve();
}).then(() => {
p.set(70);
window.__runBoot(false);
})
.script(function () {
return {src: BaseAppEditorScriptLink, type: 'text/javascript', charset: 'utf-8'};
})
.wait(function () {
runMainBoot(false);
}).catch((e) => {
runMainBoot(true);
throw e;
}).then(() => {
return window.jsloader(appData.StaticEditorJsLink);
}).then(() => {
if (window.CKEDITOR && window.__initEditor) {
window.__initEditor();
window.__initEditor = null;
@ -162,6 +213,41 @@ window.__runApp = (BaseAppLibsScriptLink, BaseAppMainScriptLink, BaseAppEditorSc
}
else
{
window.__runBoot(true);
runMainBoot(true);
}
}
window.__initAppData = function(data) {
rlAppDataStorage = data;
window.__rlah_set();
if (rlAppDataStorage.NewThemeLink)
{
window.document.getElementById('app-theme-link').href = rlAppDataStorage.NewThemeLink;
}
if (rlAppDataStorage.IncludeCss)
{
includeStyle(rlAppDataStorage.IncludeCss);
}
showDescriptionAndLoading(rlAppDataStorage ? (rlAppDataStorage.LoadingDescriptionEsc || '') : '');
runApp();
};
window.__runBoot = function() {
if (!window.navigator || !window.navigator.cookieEnabled)
{
window.document.location.replace('./?/NoCookie');
}
if (includeLayout())
{
includeAppScr(getRainloopBootData());
}
};

25
dev/Common/Loader.jsx Normal file
View file

@ -0,0 +1,25 @@
import window from 'window';
import {Promise} from 'es6-promise-polyfill/promise.js';
window.Promise = window.Promise || Promise;
export default (url) => {
return new window.Promise((resolve, reject) => {
const element = document.createElement('script');
element.onload = () => {
resolve(url);
};
element.onerror = () => {
reject(new Error(url));
};
element.async = true;
element.src = url;
document.body.appendChild(element);
});
};

View file

@ -1419,7 +1419,7 @@
aContent.push('' + sKey + '=' + sValue);
});
$('#rl-head-viewport').attr('content', aContent.join(', '));
$('#app-head-viewport').attr('content', aContent.join(', '));
};
/**
@ -1538,8 +1538,8 @@
Utils.changeTheme = function (sValue, themeTrigger)
{
var
oThemeLink = $('#rlThemeLink'),
oThemeStyle = $('#rlThemeStyle'),
oThemeLink = $('#app-theme-link'),
oThemeStyle = $('#app-theme-style'),
sUrl = oThemeLink.attr('href')
;
@ -1576,7 +1576,7 @@
{
if (oThemeLink && oThemeLink[0] && (!oThemeStyle || !oThemeStyle[0]))
{
oThemeStyle = $('<style id="rlThemeStyle"></style>');
oThemeStyle = $('<style id="app-theme-style"></style>');
oThemeLink.after(oThemeStyle);
oThemeLink.remove();
}

24
dev/Html/Layout.html Normal file
View file

@ -0,0 +1,24 @@
<div id="rl-bg" class="thm-body"></div>
<div id="rl-loading" class="thm-loading" style="opacity:0">
<div id="rl-loading-desc"></div>
<div class="e-spinner">
<div class="e-bounce bounce1"></div>
<div class="e-bounce bounce2"></div>
<div class="e-bounce bounce3"></div>
</div>
</div>
<div id="rl-loading-error" class="thm-loading">
An error occurred. <br /> Please refresh the page and try again.
<div id="rl-loading-error-additional"></div>
</div>
<div id="rl-content">
<div id="rl-popups"></div>
<div id="rl-center">
<div id="rl-top"></div>
<div id="rl-left"></div>
<div id="rl-right"></div>
<div id="rl-bottom"></div>
</div>
</div>
<div id="rl-templates"></div>
<div id="rl-hidden"></div>

View file

@ -32,7 +32,7 @@ class RainLoopStorage
setHash() {
const
key = 'AuthAccountHash',
appData = window.rainloopAppData
appData = window.__rlah_data()
;
if (this.s)
{

View file

@ -8,7 +8,7 @@ class SettingsStorage
appSettings = {};
constructor() {
this.settings = window.rainloopAppData || {};
this.settings = window.__rlah_data() || {};
this.settings = Utils.isNormal(this.settings) ? this.settings : {};
this.appSettings = this.settings.System || null;

View file

@ -349,7 +349,7 @@ html.rl-ctrl-key-pressed {
#rl-loading, #rl-loading-error {
position: absolute;
font-size: 30px;
line-height: 100%;
line-height: 130%;
top: 50%;
width: 100%;
height: 65px;
@ -370,6 +370,14 @@ html.rl-ctrl-key-pressed {
font-size: 20px;
}
#rl-app{
display: none;
}
#rl-check{
display: block;
}
html.rl-mobile .hide-on-mobile {
display: none !important;
}

View file

@ -28,10 +28,6 @@
opacity: 0;
}
#rl-check {
display: block;
}
.opentip-container {
z-index: 2001 !important;

View file

@ -1,12 +1,27 @@
import window from 'window';
import jsloader from 'Common/Loader';
import {progressJs} from 'progress.js/src/progress.js';
window.jsloader = jsloader;
window.progressJs = window.progressJs || progressJs();
window.progressJs.onbeforeend(() => {
if (window.$)
{
window.$('.progressjs-container').hide();
window.setTimeout(() => {
window.$('.progressjs-container').remove();
}, 100);
}
});
require('json2/json2.js');
require('modernizr/modernizr-custom.js');
require('Common/Booter.jsx');
import {$LAB} from 'labjs/LAB.src.js';
import {progressJs} from 'progress.js/src/progress.js';
window.$LAB = $LAB;
window.progressJs = progressJs;
if (window.__runBoot)
{
window.__runBoot();
}

View file

@ -48,17 +48,10 @@ export default (App) => {
window['rl']['EmailModel'] = EmailModel;
window['rl']['Enums'] = Enums;
window['__APP_BOOT'] = function (fCall) {
window.__APP_BOOT = function (fCall) {
$(_.delay(function () {
if (!$('#rl-check').is(':visible'))
{
Globals.$html.addClass('no-css');
}
$('#rl-check').remove();
if (window['rainloopTEMPLATES'] && window['rainloopTEMPLATES'][0])
{
$('#rl-templates').html(window['rainloopTEMPLATES'][0]);
@ -79,7 +72,7 @@ export default (App) => {
fCall(false);
}
window['__APP_BOOT'] = null;
window.__APP_BOOT = null;
}, 10));
};

View file

@ -97,7 +97,7 @@ function copyFile(sFile, sNewFile, callback)
callback();
}
cfg.paths.globjs = 'dev/**/*.{js,jsx}';
cfg.paths.globjs = 'dev/**/*.{js,jsx,html}';
cfg.paths.globjsonly = 'dev/**/*.js';
cfg.paths.globjsxonly = 'dev/**/*.jsx';
cfg.paths.static = 'rainloop/v/' + cfg.devVersion + '/static/';
@ -260,7 +260,6 @@ gulp.task('package:community-off', function() {
});
gulp.task('css:clear-less', ['css:main-begin'], function() {
return gulp.src(cfg.paths.staticCSS + cfg.paths.less.main.name, {read: false})
.pipe(require('gulp-rimraf')());
});

View file

@ -2,7 +2,7 @@
"name": "RainLoop",
"title": "RainLoop Webmail",
"version": "1.10.0",
"release": "108",
"release": "112",
"ownCloudPackageVersion": "4.16",
"description": "Simple, modern & fast web-based email client",
"homepage": "http://rainloop.net",
@ -84,6 +84,7 @@
"lodash": "~3.9.3",
"node-fs": "*",
"node-notifier": "~4.2.3",
"raw-loader": "^0.5.1",
"rimraf": "*",
"webpack": "*"
}

8
phpunit.xml Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit colors="true" stopOnFailure="true" syntaxCheck="true" bootstrap="tests/bootstrap.php">
<testsuites>
<testsuite name="RainLoop Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit>

View file

@ -1905,11 +1905,6 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
}
}
$sStaticCache = \md5(APP_VERSION.$this->Plugins()->Hash());
$sTheme = $this->ValidateTheme($sTheme, $bMobile);
$sNewThemeLink = './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$sStaticCache.'/Hash/-/';
if (!$aResult['Auth'])
{
if (!$bAdmin)
@ -1923,14 +1918,11 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
}
}
$sPluginsLink = '';
if (0 < $this->Plugins()->Count() && $this->Plugins()->HaveJs($bAdmin))
{
$sPluginsLink = './?/Plugins/0/'.($bAdmin ? 'Admin' : 'User').'/'.$sStaticCache.'/';
}
$sTheme = $this->ValidateTheme($sTheme, $bMobile);
$sStaticCache = $this->StaticCache();
$aResult['Theme'] = $sTheme;
$aResult['NewThemeLink'] = $sNewThemeLink;
$aResult['NewThemeLink'] = $this->ThemeLink($sTheme, $bAdmin);
$aResult['Language'] = $this->ValidateLanguage($sLanguage, '', false);
$aResult['LanguageAdmin'] = $this->ValidateLanguage($sLanguageAdmin, '', true);
@ -1940,11 +1932,23 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
$aResult['UserLanguage'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], '', false, true);
$aResult['UserLanguageAdmin'] = $this->ValidateLanguage($aResult['UserLanguageRaw'], '', true, true);
$aResult['PluginsLink'] = '';
if (0 < $this->Plugins()->Count() && $this->Plugins()->HaveJs($bAdmin))
{
$aResult['PluginsLink'] = './?/Plugins/0/'.($bAdmin ? 'Admin' : 'User').'/'.$sStaticCache.'/';
}
$aResult['LangLink'] = './?/Lang/0/'.($bAdmin ? 'Admin' : 'App').'/'.
($bAdmin ? $aResult['LanguageAdmin'] : $aResult['Language']).'/'.$sStaticCache.'/';
$aResult['TemplatesLink'] = './?/Templates/0/'.($bAdmin ? 'Admin' : 'App').'/'.$sStaticCache.'/';
$aResult['PluginsLink'] = $sPluginsLink;
$bAppJsDebug = !!$this->Config()->Get('labs', 'use_app_debug_js', false);
$aResult['StaticLibJsLink'] = $this->StaticPath('js/min/libs.js');
$aResult['StaticAppJsLink'] = $this->StaticPath('js/'.($bAppJsDebug ? '' : 'min/').($bAdmin ? 'admin' : 'app').'.js');
$aResult['StaticEditorJsLink'] = $this->StaticPath('ckeditor/ckeditor.js');
$aResult['EditorDefaultType'] = \in_array($aResult['EditorDefaultType'], array('Plain', 'Html', 'HtmlForced', 'PlainForced')) ?
$aResult['EditorDefaultType'] : 'Plain';
@ -9057,6 +9061,29 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
return $mResult;
}
/**
* @return string
*/
public function StaticCache()
{
static $sCache = null;
if (!$sCache)
{
$sCache = \md5(APP_VERSION.$this->Plugins()->Hash());
}
return $sCache;
}
/**
* @param string $sTheme
*
* @return string
*/
public function ThemeLink($sTheme, $bAdmin)
{
return './?/Css/0/'.($bAdmin ? 'Admin' : 'User').'/-/'.$sTheme.'/-/'.$this->StaticCache().'/Hash/-/';
}
/**
* @param string $sTheme
*
@ -9694,6 +9721,18 @@ NewThemeLink IncludeCss LoadingDescriptionEsc TemplatesLink LangLink IncludeBack
return isset($aLang[$sKey]) ? $aLang[$sKey] : $sKey;
}
/**
* @param string $sPath
*
* @return string
*/
public function StaticPath($sPath)
{
$sResult = \RainLoop\Utils::WebStaticPath().$sPath;
return $sResult.(false === \strpos($sResult, '?') ? '?' : '&').
($this->IsOpen() ? 'community' : 'standard');
}
/**
* @return MailSo\Cache\CacheClient|null
*/

View file

@ -241,7 +241,7 @@ class Service
$sResult .= '][owncloud:true';
}
$sResult .= '] //-->';
$sResult .= ']-->';
}
// Output result
@ -259,9 +259,7 @@ class Service
*/
private function staticPath($sPath)
{
$sResult = \RainLoop\Utils::WebStaticPath().$sPath;
return $sResult.(false === \strpos($sResult, '?') ? '?' : '&').
($this->oActions->IsOpen() ? 'v=community' : 'v=standard');
return $this->oActions->StaticPath($sPath);
}
/**
@ -283,42 +281,27 @@ class Service
$sFaviconUrl = (string) $this->oActions->Config()->Get('webmail', 'favicon_url', '');
$aData = array(
'Language' => $sLanguage,
'Theme' => $sTheme,
'FaviconPngLink' => $sFaviconUrl ? $sFaviconUrl : $this->staticPath('apple-touch-icon.png'),
'AppleTouchLink' => $sFaviconUrl ? '' : $this->staticPath('apple-touch-icon.png'),
'AppCssLink' => $this->staticPath('css/app'.($bAppCssDebug ? '' : '.min').'.css'),
'BootJsLink' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').'boot.js'),
'LibJsLink' => $this->staticPath('js/min/libs.js'),
'EditorJsLink' => $this->staticPath('ckeditor/ckeditor.js'),
'OpenPgpJsLink' => $this->staticPath('js/min/openpgp.min.js'),
'AppJsCommonLink' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').'common.js'),
'AppJsLink' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').($bAdmin ? 'admin' : 'app').'.js')
);
$aAdd = array();
$aAdd[] = $bMobile ? 'mobile' : 'no-mobile';
$aAdd[] = $bMobileDevice ? '1' : '0';
$sFaviconPngLink = $sFaviconUrl ? $sFaviconUrl : $this->staticPath('apple-touch-icon.png');
$sAppleTouchLink = $sFaviconUrl ? '' : $this->staticPath('apple-touch-icon.png');
$aTemplateParameters = array(
'{{BaseAppDataScriptLink}}' => ($bAdmin ? './?/AdminAppData' : './?/AppData').(0 < \count($aAdd) ? '@'.\implode('-', $aAdd) : '').'/',
'{{BaseAppFaviconPngLinkTag}}' => $aData['FaviconPngLink'] ? '<link rel="shortcut icon" href="'.$aData['FaviconPngLink'].'" type="image/png" />' : '',
'{{BaseAppFaviconTouchLinkTag}}' => $aData['AppleTouchLink'] ? '<link rel="apple-touch-icon" href="'.$aData['AppleTouchLink'].'" type="image/png" />' : '',
'{{BaseAppAppleTouchFile}}' => $aData['AppleTouchLink'],
'{{BaseAppMainCssLink}}' => $aData['AppCssLink'],
'{{BaseAppBootScriptLink}}' => $aData['BootJsLink'],
'{{BaseAppLibsScriptLink}}' => $aData['LibJsLink'],
'{{BaseAppEditorScriptLink}}' => $aData['EditorJsLink'],
'{{BaseAppOpenPgpScriptLink}}' => $aData['OpenPgpJsLink'],
'{{BaseAppMainCommonScriptLink}}' => $aData['AppJsCommonLink'],
'{{BaseAppMainScriptLink}}' => $aData['AppJsLink'],
'{{BaseVersion}}' => APP_VERSION,
'{{BaseAppFaviconPngLinkTag}}' => $sFaviconPngLink ? '<link type="image/png" rel="shortcut icon" href="'.$sFaviconPngLink.'" />' : '',
'{{BaseAppFaviconTouchLinkTag}}' => $sAppleTouchLink ? '<link type="image/png" rel="apple-touch-icon" href="'.$sAppleTouchLink.'" />' : '',
'{{BaseAppMainCssLink}}' => $this->staticPath('css/app'.($bAppCssDebug ? '' : '.min').'.css'),
'{{BaseAppThemeCssLink}}' => $this->oActions->ThemeLink($sTheme, $bAdmin),
'{{BaseAppBootScriptLink}}' => $this->staticPath('js/'.($bAppJsDebug ? '' : 'min/').'boot.js'),
'{{BaseViewport}}' => $bMobile ? 'width=device-width,initial-scale=1,user-scalable=no' : 'width=950,maximum-scale=2',
'{{BaseDir}}' => 'ltr'
// '{{BaseDir}}' => \in_array($aData['Language'], array('ar', 'he', 'ur')) ? 'rtl' : 'ltr'
'{{BaseDir}}' => false && \in_array($sLanguage, array('ar', 'he', 'ur')) ? 'rtl' : 'ltr'
);
$aTemplateParameters['{{RainloopBootData}}'] = \json_encode(array(
'admin' => $bAdmin,
'language' => $sLanguage,
'theme' => $sTheme,
'mobile' => $bMobile,
'mobileDevice' => $bMobileDevice
));
$aTemplateParameters['{{BaseHash}}'] = \md5(
\implode('~', array(
$bAdmin ? '1' : '0',

View file

@ -1369,9 +1369,8 @@ class ServiceActions
private function compileAppData($aAppData, $bWrapByScriptTag = true)
{
return
($bWrapByScriptTag ? '<script data-cfasync="false">' : '').
'window.rainloopAppData='.\json_encode($aAppData).';'.
'if(window.__rlah_set){__rlah_set()};'.
($bWrapByScriptTag ? '<script type="text/javascript" data-cfasync="false">' : '').
'if(window.__initAppData){window.__initAppData('.\json_encode($aAppData).');}'.
($bWrapByScriptTag ? '</script>' : '')
;
}

View file

@ -475,12 +475,13 @@ class Utils
public static function ClearHtmlOutput($sHtml)
{
// return $sHtml;
return \str_replace('> <', '><',
return \trim(\str_replace('> <', '><',
\str_replace('" />', '"/>',
\preg_replace('/[\s]+&nbsp;/i', '&nbsp;',
\preg_replace('/&nbsp;[\s]+/i', '&nbsp;',
\preg_replace('/[\r\n\t]+/', ' ',
$sHtml
))));
))))));
}
/**

View file

@ -1,74 +1,29 @@
<!DOCTYPE html>
<html class="no-js rl-booted-trigger rl-started-trigger" dir="{{BaseDir}}">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta id="rl-head-viewport" name="viewport" content="{{BaseViewport}}">
<meta name="apple-mobile-web-app-capable" content="yes" />
<noscript>
<meta http-equiv="refresh" content="0; URL=./?/NoScript" />
</noscript>
<!--[if lte IE 8]>
<meta http-equiv="refresh" content="0; URL=./?/BadBrowser" />
<![endif]-->
<script type="text/javascript" data-cfasync="false">
if (!window.navigator || !window.navigator.cookieEnabled) {
window.document.location.replace('./?/NoCookie');
}
</script>
<meta name="Author" content="RainLoop Team" />
<meta name="robots" content="noindex,nofollow,noodp" />
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="{{BaseViewport}}" id="app-head-viewport">
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="google" content="notranslate" />
<meta name="robots" content="noindex,nofollow,noodp" />
<meta name="AppBootData" content='{{RainloopBootData}}' id="app-boot-data" />
<title></title>
<style>#rl-content{display:none;}#rl-check{display:none;}</style>
{{BaseAppFaviconPngLinkTag}}{{BaseAppFaviconTouchLinkTag}}
{{BaseAppFaviconPngLinkTag}}
{{BaseAppFaviconTouchLinkTag}}
<style>#rl-check{display:none}</style>
<link type="text/css" rel="stylesheet" href="{{BaseAppMainCssLink}}" />
<link type="text/css" rel="stylesheet" id="rlThemeLink" />
<script type="text/javascript" data-cfasync="false" src="{{BaseAppBootScriptLink}}"></script>
<script type="text/javascript" data-cfasync="false">
window.__includeAppScr('{{BaseAppDataScriptLink}}');
</script>
<script type="text/javascript" data-cfasync="false">
if (window.rainloopAppData && window.rainloopAppData['NewThemeLink']) {
window.document.getElementById('rlThemeLink').href = window.rainloopAppData['NewThemeLink'];
}
</script>
<script type="text/javascript" data-cfasync="false">
if (window.rainloopAppData && window.rainloopAppData['IncludeCss']) {
window.__includeStyle(window.rainloopAppData['IncludeCss']);
}
</script>
<script type="text/javascript" data-cfasync="false"></script>
<link type="text/css" rel="stylesheet" href="{{BaseAppThemeCssLink}}" id="app-theme-link" />
</head>
<body>
<div id="rl-app"></div>
<div id="rl-check"></div>
<div id="rl-bg" class="thm-body"></div>
<div id="rl-loading" class="thm-loading">
<div id="rl-loading-desc">Loading</div>
<div class="e-spinner">
<div class="e-bounce bounce1"></div>
<div class="e-bounce bounce2"></div>
<div class="e-bounce bounce3"></div>
</div>
</div>
<div id="rl-loading-error" class="thm-loading">
An Error occurred,
<br />
please refresh the page and try again.
<div id="rl-loading-error-additional"></div>
</div>
<div id="rl-content">
<div id="rl-popups"></div>
<div id="rl-center">
<div id="rl-top"></div>
<div id="rl-left"></div>
<div id="rl-right"></div>
<div id="rl-bottom"></div>
</div>
</div>
<div id="rl-templates"></div>
<div id="rl-hidden"></div>
<script type="text/javascript" data-cfasync="false">__showDescription(window.rainloopAppData ? window.rainloopAppData['LoadingDescriptionEsc'] : '');</script>
<script type="text/javascript" data-cfasync="false">__runApp('{{BaseAppLibsScriptLink}}', '{{BaseAppMainScriptLink}}', '{{BaseAppEditorScriptLink}}');</script>
<script type="text/javascript" data-cfasync="false" src="{{BaseAppBootScriptLink}}"></script>
</body>
</html>

View file

@ -187,9 +187,39 @@
.thm-rgba-background-color(@message-background-color, @message-rgba-background-color);
}
#rl-app{
display: block;
}
html.no-css {
margin: 0;
padding: 0;
font-family: Arial, Verdana, Geneva, sans-serif;
body {
margin: 0;
padding: 0;
}
#rl-loading, #rl-loading-error {
position: absolute;
font-size: 30px;
line-height: 130%;
top: 50%;
width: 100%;
height: 65px;
margin: 0;
margin-top: -60px;
background-color: transparent;
text-align: center;
color: #333;
}
.progressjs-container {
display: none;
}
.thm-body {
color: #333;
background-color: #aaa;

View file

@ -3,13 +3,12 @@
<div class="btn-toolbar">
<div class="btn-group btn-group-last pull-right dropdown colored-toggle" data-bind="registrateBootstrapDropdown: true, openDropdownTrigger: accountMenuDropdownTrigger">
<a id="top-system-dropdown-id" href="#" tabindex="-1" class="btn single btn-ellipsis btn-block dropdown-toggle system-dropdown" data-toggle="dropdown">
<i data-bind="css: {'icon-user': !accounts.loading(), 'icon-spinner animated': accounts.loading()}"
></i>
<i data-bind="css: {'icon-user': !accounts.loading(), 'icon-spinner animated': accounts.loading()}"></i>
<!--
<b data-bind="text: accountsUnreadCount, visible: 100 > accountsUnreadCount() && 0 < accountsUnreadCount()"></b>
<b data-bind="visible: 99 < accountsUnreadCount()">99+</b>
-->
&nbsp;
-->
&nbsp;
<span class="caret"></span>
</a>

View file

@ -1,6 +0,0 @@
module.exports = {
url: 'https://mail.rainloop.net/',
testLogin: 'demo@rainloop.test',
testPassword: '12345'
};

1
tests/bootstrap.php Normal file
View file

@ -0,0 +1 @@
<?php

View file

@ -1,70 +0,0 @@
var cfg = require('./_config.js');
casper.start(cfg.url);
casper.then(function() {
this.echo('testing: ' + cfg.url);
}).wait(100);
casper.then(function() {
casper.test.begin('Login page should contains "Sign In" button', 1, function (test) {
casper.then(function() {
test.assertExists('button.buttonLogin');
});
casper.then(function() {
test.done();
});
});
casper.test.begin('Login page should allow langs selection', 3, function (test) {
casper.then(function() {
test.assertExists('.e-languages .flag-selector .flag-name');
});
casper.then(function() {
this.click('.e-languages .flag-selector .flag-name');
}).wait(300);
casper.then(function() {
test.assertExists('.b-languages-content');
});
casper.then(function() {
this.click('.b-languages-content .lang-item .flag.flag-ru_ru');
}).wait(1000);
casper.then(function() {
test.assertEquals('Войти', this.fetchText('button.buttonLogin'));
});
casper.then(function() {
test.done();
});
});
casper.test.begin('Login page submit', 1, function (test) {
casper.then(function() {
this.fill('form.loginForm', {
'RainLoopEmail': cfg.testLogin,
'RainLoopPassword': cfg.testPassword
}, true);
}).wait(3000);
casper.then(function() {
test.assertEquals(cfg.testLogin, this.fetchText('.accountPlace'));
});
casper.then(function() {
test.done();
});
});
});
casper.run();

View file

@ -0,0 +1,2 @@
/node_modules
/tmp

View file

@ -0,0 +1,3 @@
/node_modules/
/tmp
/test

View file

@ -0,0 +1,6 @@
language: node_js
sudo: false
node_js:
- "0.12"
- "node"
- "iojs"

View file

@ -0,0 +1,18 @@
## 1.2.0 (December 8, 2015)
- Support for IE8 and below
- Promises/A+ tests added
## 1.1.0 (October 16, 2015)
- Change way to get reference to `global`, since `Function()()` may be prohibited
- Add AMD support
## 1.0.1 (September 14, 2015)
- Fix exports - use polyfill only if native implementation isn't supported
- Add license
## 1.0.0 (June 19, 2014)
- Init release

View file

@ -1,4 +1,6 @@
Copyright 2015 RainLoop Team
(The MIT License)
Copyright (c) 2014 Roman Dvornov
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

88
vendors/es6-promise-polyfill/README.md vendored Normal file
View file

@ -0,0 +1,88 @@
[![NPM version](https://img.shields.io/npm/v/es6-promise-polyfill.svg)](https://www.npmjs.com/package/es6-promise-polyfill)
[![Build Status](https://travis-ci.org/lahmatiy/es6-promise-polyfill.svg?branch=master)](https://travis-ci.org/lahmatiy/es6-promise-polyfill)
# ES6 Promise polyfill
This is a polyfill of [ES6 Promise](https://github.com/domenic/promises-unwrapping). The implementation based on [Jake Archibald implementation](https://github.com/jakearchibald/es6-promise) a subset of [rsvp.js](https://github.com/tildeio/rsvp.js). If you're wanting extra features and more debugging options, check out the [full library](https://github.com/tildeio/rsvp.js).
For API details and how to use promises, see the <a href="http://www.html5rocks.com/en/tutorials/es6/promises/">JavaScript Promises HTML5Rocks article</a>.
## Notes
The main target: implementation should be conformance with browser's implementations and to be minimal as possible in size. So it's strictly polyfill of ES6 Promise specification and nothing more.
It passes both [Promises/A+ test suite](https://github.com/promises-aplus/promises-tests) and [rsvp.js test suite](https://github.com/jakearchibald/es6-promise/tree/master/test). And as small as 2,6KB min (or 1KB min+gzip).
The polyfill uses `setImmediate` if available, or fallback to use `setTimeout`. Use [setImmediate polyfill](https://github.com/YuzuJS/setImmediate) by @YuzuJS to reach better performance.
## How to use
### Browser
To install:
```sh
bower install es6-promise-polyfill
```
To use:
```html
<script src="bower_components/es6-promise-polyfill/promise.min.js"></script>
<script>
var promise = new Promise(...);
</script>
```
### Node.js
To install:
```sh
npm install es6-promise-polyfill
```
To use:
```js
var Promise = require('es6-promise-polyfill').Promise;
var promise = new Promise(...);
```
### AMD
To install:
```sh
npm install es6-promise-polyfill
```
To use:
```js
define(['es6-promise-polyfill'], function(Promise) {
var promise = new Promise(...);
});
```
## Usage in IE<9
`catch` is a reserved word in IE<9, meaning `promise.catch(func)` throws a syntax error. To work around this, use a string to access the property:
```js
promise['catch'](function(err) {
// ...
});
```
Or use `.then` instead:
```js
promise.then(undefined, function(err) {
// ...
});
```
## License
Licensed under the MIT License.

11
vendors/es6-promise-polyfill/bower.json vendored Normal file
View file

@ -0,0 +1,11 @@
{
"name": "es6-promise-polyfill",
"version": "1.1.1",
"main": "promise.js",
"ignore": [
".*",
"**/.*",
"node_modules",
"test"
]
}

View file

@ -0,0 +1,27 @@
{
"name": "es6-promise-polyfill",
"description": "Polyfill for ES6 Promise",
"version": "1.2.0",
"author": "Roman Dvornov <rdvornov@gmail.com>",
"license": "MIT",
"repository": "lahmatiy/es6-promise-polyfill",
"bugs": {
"url": "https://github.com/lahmatiy/es6-promise-polyfill/issues"
},
"main": "promise.js",
"dependencies": {
},
"devDependencies": {
"promises-aplus-tests": "*"
},
"scripts": {
"test": "promises-aplus-tests test/test-adapter"
},
"keywords": [
"es6",
"es2015",
"polyfill",
"promise",
"promises"
]
}

346
vendors/es6-promise-polyfill/promise.js vendored Normal file
View file

@ -0,0 +1,346 @@
(function(global){
//
// Check for native Promise and it has correct interface
//
var NativePromise = global['Promise'];
var nativePromiseSupported =
NativePromise &&
// Some of these methods are missing from
// Firefox/Chrome experimental implementations
'resolve' in NativePromise &&
'reject' in NativePromise &&
'all' in NativePromise &&
'race' in NativePromise &&
// Older version of the spec had a resolver object
// as the arg rather than a function
(function(){
var resolve;
new NativePromise(function(r){ resolve = r; });
return typeof resolve === 'function';
})();
//
// export if necessary
//
if (typeof exports !== 'undefined' && exports)
{
// node.js
exports.Promise = nativePromiseSupported ? NativePromise : Promise;
exports.Polyfill = Promise;
}
else
{
// AMD
if (typeof define == 'function' && define.amd)
{
define(function(){
return nativePromiseSupported ? NativePromise : Promise;
});
}
else
{
// in browser add to global
if (!nativePromiseSupported)
global['Promise'] = Promise;
}
}
//
// Polyfill
//
var PENDING = 'pending';
var SEALED = 'sealed';
var FULFILLED = 'fulfilled';
var REJECTED = 'rejected';
var NOOP = function(){};
function isArray(value) {
return Object.prototype.toString.call(value) === '[object Array]';
}
// async calls
var asyncSetTimer = typeof setImmediate !== 'undefined' ? setImmediate : setTimeout;
var asyncQueue = [];
var asyncTimer;
function asyncFlush(){
// run promise callbacks
for (var i = 0; i < asyncQueue.length; i++)
asyncQueue[i][0](asyncQueue[i][1]);
// reset async asyncQueue
asyncQueue = [];
asyncTimer = false;
}
function asyncCall(callback, arg){
asyncQueue.push([callback, arg]);
if (!asyncTimer)
{
asyncTimer = true;
asyncSetTimer(asyncFlush, 0);
}
}
function invokeResolver(resolver, promise) {
function resolvePromise(value) {
resolve(promise, value);
}
function rejectPromise(reason) {
reject(promise, reason);
}
try {
resolver(resolvePromise, rejectPromise);
} catch(e) {
rejectPromise(e);
}
}
function invokeCallback(subscriber){
var owner = subscriber.owner;
var settled = owner.state_;
var value = owner.data_;
var callback = subscriber[settled];
var promise = subscriber.then;
if (typeof callback === 'function')
{
settled = FULFILLED;
try {
value = callback(value);
} catch(e) {
reject(promise, e);
}
}
if (!handleThenable(promise, value))
{
if (settled === FULFILLED)
resolve(promise, value);
if (settled === REJECTED)
reject(promise, value);
}
}
function handleThenable(promise, value) {
var resolved;
try {
if (promise === value)
throw new TypeError('A promises callback cannot return that same promise.');
if (value && (typeof value === 'function' || typeof value === 'object'))
{
var then = value.then; // then should be retrived only once
if (typeof then === 'function')
{
then.call(value, function(val){
if (!resolved)
{
resolved = true;
if (value !== val)
resolve(promise, val);
else
fulfill(promise, val);
}
}, function(reason){
if (!resolved)
{
resolved = true;
reject(promise, reason);
}
});
return true;
}
}
} catch (e) {
if (!resolved)
reject(promise, e);
return true;
}
return false;
}
function resolve(promise, value){
if (promise === value || !handleThenable(promise, value))
fulfill(promise, value);
}
function fulfill(promise, value){
if (promise.state_ === PENDING)
{
promise.state_ = SEALED;
promise.data_ = value;
asyncCall(publishFulfillment, promise);
}
}
function reject(promise, reason){
if (promise.state_ === PENDING)
{
promise.state_ = SEALED;
promise.data_ = reason;
asyncCall(publishRejection, promise);
}
}
function publish(promise) {
var callbacks = promise.then_;
promise.then_ = undefined;
for (var i = 0; i < callbacks.length; i++) {
invokeCallback(callbacks[i]);
}
}
function publishFulfillment(promise){
promise.state_ = FULFILLED;
publish(promise);
}
function publishRejection(promise){
promise.state_ = REJECTED;
publish(promise);
}
/**
* @class
*/
function Promise(resolver){
if (typeof resolver !== 'function')
throw new TypeError('Promise constructor takes a function argument');
if (this instanceof Promise === false)
throw new TypeError('Failed to construct \'Promise\': Please use the \'new\' operator, this object constructor cannot be called as a function.');
this.then_ = [];
invokeResolver(resolver, this);
}
Promise.prototype = {
constructor: Promise,
state_: PENDING,
then_: null,
data_: undefined,
then: function(onFulfillment, onRejection){
var subscriber = {
owner: this,
then: new this.constructor(NOOP),
fulfilled: onFulfillment,
rejected: onRejection
};
if (this.state_ === FULFILLED || this.state_ === REJECTED)
{
// already resolved, call callback async
asyncCall(invokeCallback, subscriber);
}
else
{
// subscribe
this.then_.push(subscriber);
}
return subscriber.then;
},
'catch': function(onRejection) {
return this.then(null, onRejection);
}
};
Promise.all = function(promises){
var Class = this;
if (!isArray(promises))
throw new TypeError('You must pass an array to Promise.all().');
return new Class(function(resolve, reject){
var results = [];
var remaining = 0;
function resolver(index){
remaining++;
return function(value){
results[index] = value;
if (!--remaining)
resolve(results);
};
}
for (var i = 0, promise; i < promises.length; i++)
{
promise = promises[i];
if (promise && typeof promise.then === 'function')
promise.then(resolver(i), reject);
else
results[i] = promise;
}
if (!remaining)
resolve(results);
});
};
Promise.race = function(promises){
var Class = this;
if (!isArray(promises))
throw new TypeError('You must pass an array to Promise.race().');
return new Class(function(resolve, reject) {
for (var i = 0, promise; i < promises.length; i++)
{
promise = promises[i];
if (promise && typeof promise.then === 'function')
promise.then(resolve, reject);
else
resolve(promise);
}
});
};
Promise.resolve = function(value){
var Class = this;
if (value && typeof value === 'object' && value.constructor === Class)
return value;
return new Class(function(resolve){
resolve(value);
});
};
Promise.reject = function(reason){
var Class = this;
return new Class(function(resolve, reject){
reject(reason);
});
};
})(typeof window != 'undefined' ? window : typeof global != 'undefined' ? global : typeof self != 'undefined' ? self : this);

View file

@ -0,0 +1,6 @@
(function(t){function z(){for(var a=0;a<g.length;a++)g[a][0](g[a][1]);g=[];m=!1}function n(a,b){g.push([a,b]);m||(m=!0,A(z,0))}function B(a,b){function c(a){p(b,a)}function h(a){k(b,a)}try{a(c,h)}catch(d){h(d)}}function u(a){var b=a.owner,c=b.state_,b=b.data_,h=a[c];a=a.then;if("function"===typeof h){c=l;try{b=h(b)}catch(d){k(a,d)}}v(a,b)||(c===l&&p(a,b),c===q&&k(a,b))}function v(a,b){var c;try{if(a===b)throw new TypeError("A promises callback cannot return that same promise.");if(b&&("function"===
typeof b||"object"===typeof b)){var h=b.then;if("function"===typeof h)return h.call(b,function(d){c||(c=!0,b!==d?p(a,d):w(a,d))},function(b){c||(c=!0,k(a,b))}),!0}}catch(d){return c||k(a,d),!0}return!1}function p(a,b){a!==b&&v(a,b)||w(a,b)}function w(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(C,a))}function k(a,b){a.state_===r&&(a.state_=x,a.data_=b,n(D,a))}function y(a){var b=a.then_;a.then_=void 0;for(a=0;a<b.length;a++)u(b[a])}function C(a){a.state_=l;y(a)}function D(a){a.state_=q;y(a)}function e(a){if("function"!==
typeof a)throw new TypeError("Promise constructor takes a function argument");if(!1===this instanceof e)throw new TypeError("Failed to construct 'Promise': Please use the 'new' operator, this object constructor cannot be called as a function.");this.then_=[];B(a,this)}var f=t.Promise,s=f&&"resolve"in f&&"reject"in f&&"all"in f&&"race"in f&&function(){var a;new f(function(b){a=b});return"function"===typeof a}();"undefined"!==typeof exports&&exports?(exports.Promise=s?f:e,exports.Polyfill=e):"function"==
typeof define&&define.amd?define(function(){return s?f:e}):s||(t.Promise=e);var r="pending",x="sealed",l="fulfilled",q="rejected",E=function(){},A="undefined"!==typeof setImmediate?setImmediate:setTimeout,g=[],m;e.prototype={constructor:e,state_:r,then_:null,data_:void 0,then:function(a,b){var c={owner:this,then:new this.constructor(E),fulfilled:a,rejected:b};this.state_===l||this.state_===q?n(u,c):this.then_.push(c);return c.then},"catch":function(a){return this.then(null,a)}};e.all=function(a){if("[object Array]"!==
Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.all().");return new this(function(b,c){function h(a){e++;return function(c){d[a]=c;--e||b(d)}}for(var d=[],e=0,f=0,g;f<a.length;f++)(g=a[f])&&"function"===typeof g.then?g.then(h(f),c):d[f]=g;e||b(d)})};e.race=function(a){if("[object Array]"!==Object.prototype.toString.call(a))throw new TypeError("You must pass an array to Promise.race().");return new this(function(b,c){for(var e=0,d;e<a.length;e++)(d=a[e])&&"function"===
typeof d.then?d.then(b,c):b(d)})};e.resolve=function(a){return a&&"object"===typeof a&&a.constructor===this?a:new this(function(b){b(a)})};e.reject=function(a){return new this(function(b,c){c(a)})}})("undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:this);

View file

@ -0,0 +1,22 @@
var assert = require('assert');
var Promise = require('../promise').Polyfill;
var resolve = Promise.resolve;
var reject = Promise.reject;
function defer(){
var deferred = {};
deferred.promise = new Promise(function(resolve, reject){
deferred.resolve = resolve;
deferred.reject = reject;
});
return deferred;
}
module.exports = {
resolved: function(a){ return Promise.resolve(a); },
rejected: function(a){ return Promise.reject(a); },
deferred: defer,
Promise: Promise
};

View file

@ -1,2 +0,0 @@
/*! RainLoop Index Helper v1.5 (c) 2015 RainLoop Team; Licensed under MIT */
!function(t,e,n){function r(){}r.prototype.s=t.sessionStorage,r.prototype.t=t.top||t,r.prototype.getHash=function(){var t=null;if(this.s)t=this.s.getItem("__rlA")||null;else if(this.t){var e=this.t.name&&n&&"{"===this.t.name.toString().substr(0,1)?n.parse(this.t.name.toString()):null;t=e?e.__rlA||null:null}return t},r.prototype.setHash=function(){var e=t.rainloopAppData,r=null;this.s?this.s.setItem("__rlA",e&&e.AuthAccountHash?e.AuthAccountHash:""):this.t&&n&&(r={},r.__rlA=e&&e.AuthAccountHash?e.AuthAccountHash:"",this.t.name=n.stringify(r))},r.prototype.clearHash=function(){this.s?this.s.setItem("__rlA",""):this.t&&(this.t.name="")},t._rlhh=new r,t.__rlah=function(){return t._rlhh?t._rlhh.getHash():null},t.__rlah_set=function(){t._rlhh&&t._rlhh.setHash()},t.__rlah_clear=function(){t._rlhh&&t._rlhh.clearHash()},t.__includeScr=function(t){e.write(unescape('%3Cscript data-cfasync="false" type="text/javascript" src="'+t+'"%3E%3C/script%3E'))},t.__includeStyle=function(t){e.write(unescape("%3Cstyle%3E"+t+'"%3E%3C/style%3E'))},t.__showError=function(n){var r=e.getElementById("rl-loading"),s=e.getElementById("rl-loading-error"),l=e.getElementById("rl-loading-error-additional");r&&(r.style.display="none"),s&&(s.style.display="block"),l&&n&&(l.style.display="block",l.innerHTML=n),t.SimplePace&&t.SimplePace.set(100)},t.__simplePace=function(e){t.SimplePace&&t.SimplePace.add(e)},t.__runBoot=function(e,n){t.__APP_BOOT&&!e?t.__APP_BOOT(function(t){t||__showError(n)}):__showError(n)}}(window,window.document,window.JSON);

105
vendors/rl/rl.js vendored
View file

@ -1,105 +0,0 @@
/*! RainLoop Index Helper v1.5 (c) 2015 RainLoop Team; Licensed under MIT */
(function (window, document, JSON, undefined) {
/**
* @constructor
*/
function CRLTopDriver() {}
CRLTopDriver.prototype.s = window['sessionStorage'] || null;
CRLTopDriver.prototype.t = window['top'] || window;
/**
* @return {(string|null)}
*/
CRLTopDriver.prototype['getHash'] = function() {
var mR = null;
if (this.s) {
mR = this.s['getItem']('__rlA') || null;
} else if (this.t) {
var mData = this.t['name'] && JSON && '{' === this.t['name']['toString']()['substr'](0, 1) ? JSON['parse'](this.t['name']['toString']()) : null;
mR = mData ? (mData['__rlA'] || null) : null;
}
return mR;
};
CRLTopDriver.prototype['setHash'] = function() {
var mData = window['rainloopAppData'], mRes = null;
if (this.s) {
this.s['setItem']('__rlA', mData && mData['AuthAccountHash'] ? mData['AuthAccountHash'] : '');
} else if (this.t && JSON) {
mRes = {};
mRes['__rlA'] = mData && mData['AuthAccountHash'] ? mData['AuthAccountHash'] : '';
this.t['name'] = JSON['stringify'](mRes);
}
};
CRLTopDriver.prototype['clearHash'] = function() {
if (this.s) {
this.s['setItem']('__rlA', '');
} else if (this.t) {
this.t['name'] = '';
}
};
window['_rlhh'] = new CRLTopDriver();
/**
* @returns {(string|null)}
*/
window['__rlah'] = function () {
return window['_rlhh'] ? window['_rlhh']['getHash']() : null;
};
window['__rlah_set'] = function () {
if (window['_rlhh']) {
window['_rlhh']['setHash']();
}
};
window['__rlah_clear'] = function () {
if (window['_rlhh']) {
window['_rlhh']['clearHash']();
}
};
// index function
window['__includeScr'] = function (sSrc) {
document.write(unescape('%3Csc' + 'ript data-cfasync="false" type="text/jav' + 'ascr' + 'ipt" sr' + 'c="' + sSrc + '"%3E%3C/' + 'scr' + 'ipt%3E'));
};
window['__includeStyle'] = function (sStyles) {
document.write(unescape('%3Csty' + 'le%3E' + sStyles + '"%3E%3C/' + 'sty' + 'le%3E'));
};
window['__showError'] = function (sAdditionalError) {
var oR = document.getElementById('rl-loading'),
oL = document.getElementById('rl-loading-error'),
oLA = document.getElementById('rl-loading-error-additional');
if (oR) {oR.style.display = 'none';}
if (oL) {oL.style.display = 'block';}
if (oLA && sAdditionalError) { oLA.style.display = 'block'; oLA.innerHTML = sAdditionalError; }
if (window.SimplePace) {window.SimplePace.set(100);}
};
window['__simplePace'] = function (nVal) {
if (window.SimplePace) {
window.SimplePace.add(nVal);
}
};
window['__runBoot'] = function (bWithError, sAdditionalError) {
if (window.__APP_BOOT && !bWithError) {
window.__APP_BOOT(function (bV) {
if (!bV) {
__showError(sAdditionalError);
}
});
} else {
__showError(sAdditionalError);
}
};
}(window, window.document, window.JSON));

View file

@ -32,6 +32,10 @@ module.exports = {
},
module: {
loaders: [
{
test: /\.html$/,
loader: 'raw'
},
{
test: /\.jsx$/,
loader: 'babel',
@ -49,7 +53,7 @@ module.exports = {
'JSON': 'window.JSON',
'JSEncrypt': 'window.JSEncrypt',
'$LAB': 'window.$LAB',
'progressJs': 'window.rainloopProgressJs',
'progressJs': 'window.progressJs',
'queue': 'window.queue',
'moment': 'window.moment',
'ifvisible': 'window.ifvisible',