diff --git a/.eslintignore b/.eslintignore index 0fb9f18e5..4682851df 100644 --- a/.eslintignore +++ b/.eslintignore @@ -2,7 +2,7 @@ # libraries web/api/lib -web/includes/csrf/csrf-magic.js +web/includes/csrf/ web/js/videojs.zoomrotate.js web/skins/classic/js/bootstrap.js web/skins/classic/js/chosen @@ -13,3 +13,7 @@ web/skins/classic/js/jquery.js web/skins/classic/js/moment.js web/skins/classic/js/video.js web/tools/mootools + +# Cannot be parsed as JS +web/skins/classic/includes/export_functions.php +web/skins/classic/views/events.php diff --git a/.eslintrc.js b/.eslintrc.js index dd1f9a779..64950ee0d 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -5,26 +5,46 @@ module.exports = { "browser": true, }, "extends": ["google"], + "overrides": [{ + // eslint-plugin-html handles eol-last slightly different - it applies to + // each set of script tags, so we turn it off here. + "files": "**/*.*php", + "rules": { + "eol-last": "off", + "indent": "off", + }, + }], + "plugins": [ + "html", + "php-markup", + ], "rules": { - "brace-style": "off", "camelcase": "off", "comma-dangle": "off", "guard-for-in": "off", - "key-spacing": "off", "max-len": "off", "new-cap": ["error", { capIsNewExceptions: ["Error", "Warning", "Debug", "Polygon_calcArea", "Play", "Stop"], newIsCapExceptionPattern: "^Asset\.." }], "no-array-constructor": "off", - "no-caller": "off", - "no-new-object": "off", - "no-unused-vars": "off", + "no-unused-vars": ["error", { + "vars": "local", + "args": "none", + "ignoreRestSiblings": false + }], "no-var": "off", - "object-curly-spacing": "off", "prefer-rest-params": "off", "quotes": "off", "require-jsdoc": "off", "spaced-comment": "off", }, + "settings": { + "php/php-extensions": [".php"], + "php/markup-replacement": {"php": "", "=": "0"}, + "php/keep-eol": false, + "php/remove-whitespace": false, + "php/remove-empty-line": false, + "php/remove-php-lint": false + }, }; diff --git a/.github/support.yml b/.github/support.yml index fc61e151e..c62515ee2 100644 --- a/.github/support.yml +++ b/.github/support.yml @@ -11,8 +11,10 @@ supportComment: > attempts to ask a question. Please use our support channels to get help with or discuss this project: + - The [ZoneMinder-Chat Slack channel](https://zoneminder-chat.herokuapp.com/) - - The [ZoneMinder Forum](https://forums.zoneminder.com/) + + - The [ZoneMinder USer Forum](https://forums.zoneminder.com/) # Close issues marked as support requests close: true diff --git a/.travis.yml b/.travis.yml index d46e0fc85..6c41f1123 100644 --- a/.travis.yml +++ b/.travis.yml @@ -32,24 +32,28 @@ install: - update-binfmts --enable qemu-arm env: - global: - - SMPFLAGS=-j4 - matrix: - - OS=el DIST=7 - - OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack - - OS=fedora DIST=28 DOCKER_REPO=knnniggett/packpack - - OS=fedora DIST=29 DOCKER_REPO=knnniggett/packpack - - OS=ubuntu DIST=trusty - - OS=ubuntu DIST=xenial - - OS=ubuntu DIST=trusty ARCH=i386 - - OS=ubuntu DIST=xenial ARCH=i386 - - OS=raspbian DIST=stretch ARCH=armhf DOCKER_REPO=knnniggett/packpack + - SMPFLAGS=-j4 OS=el DIST=7 + - SMPFLAGS=-j4 OS=fedora DIST=27 DOCKER_REPO=knnniggett/packpack + - SMPFLAGS=-j4 OS=fedora DIST=28 DOCKER_REPO=knnniggett/packpack + - SMPFLAGS=-j4 OS=fedora DIST=29 DOCKER_REPO=knnniggett/packpack + - SMPFLAGS=-j4 OS=ubuntu DIST=trusty + - SMPFLAGS=-j4 OS=ubuntu DIST=xenial + - SMPFLAGS=-j4 OS=ubuntu DIST=trusty ARCH=i386 + - SMPFLAGS=-j4 OS=ubuntu DIST=xenial ARCH=i386 + - SMPFLAGS=-j4 OS=raspbian DIST=stretch ARCH=armhf DOCKER_REPO=knnniggett/packpack compiler: - gcc services: - mysql - docker + +jobs: + include: + - name: eslint + install: npm install -g eslint@5.12.0 eslint-config-google@0.11.0 eslint-plugin-html@5.0.0 eslint-plugin-php-markup@0.2.5 + script: eslint --ext .php,.js . + script: - utils/packpack/startpackpack.sh @@ -65,4 +69,3 @@ deploy: script: utils/packpack/rsync_xfer.sh on: branch: master - diff --git a/src/zm_eventstream.cpp b/src/zm_eventstream.cpp index 1346167ca..4cf8ae8e1 100644 --- a/src/zm_eventstream.cpp +++ b/src/zm_eventstream.cpp @@ -770,7 +770,9 @@ void EventStream::runStream() { send_frame = false; // commands may set send_frame to true - while(checkCommandQueue()); + while ( checkCommandQueue() && !zm_terminate ) { + // The idea is to loop here processing all commands before proceeding. + } // Update modified time of the socket .lock file so that we can tell which ones are stale. if ( now.tv_sec - last_comm_update.tv_sec > 3600 ) { diff --git a/src/zm_monitor.cpp b/src/zm_monitor.cpp index 3e4aff2a4..72d9c8c2a 100644 --- a/src/zm_monitor.cpp +++ b/src/zm_monitor.cpp @@ -869,6 +869,10 @@ double Monitor::GetFPS() const { struct timeval time2 = *snap2->timestamp; double time_diff = tvDiffSec( time2, time1 ); + if ( ! time_diff ) { + Error( "No diff between time_diff = %lf (%d:%ld.%ld - %d:%ld.%ld), ibc: %d", time_diff, index2, time2.tv_sec, time2.tv_usec, index1, time1.tv_sec, time1.tv_usec, image_buffer_count ); + return 0.0; + } double curr_fps = image_count/time_diff; if ( curr_fps < 0.0 ) { diff --git a/src/zm_monitorstream.cpp b/src/zm_monitorstream.cpp index 65e9af579..0b2811656 100644 --- a/src/zm_monitorstream.cpp +++ b/src/zm_monitorstream.cpp @@ -527,8 +527,9 @@ void MonitorStream::runStream() { bool was_paused = paused; if ( connkey ) { - while(checkCommandQueue()) { -Debug(2, "Have checking command Queue for connkey: %d", connkey ); + while ( checkCommandQueue() && !zm_terminate ) { + // Loop in here until all commands are processed. + Debug(2, "Have checking command Queue for connkey: %d", connkey); got_command = true; } // Update modified time of the socket .lock file so that we can tell which ones are stale. @@ -536,8 +537,7 @@ Debug(2, "Have checking command Queue for connkey: %d", connkey ); touch(sock_path_lock); last_comm_update = now; } - - } + } // end if connkey if ( paused ) { if ( !was_paused ) { diff --git a/src/zm_stream.cpp b/src/zm_stream.cpp index ca60485ab..5db3e5ecf 100644 --- a/src/zm_stream.cpp +++ b/src/zm_stream.cpp @@ -62,8 +62,13 @@ bool StreamBase::checkInitialised() { void StreamBase::updateFrameRate(double fps) { base_fps = fps; - effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE; frame_mod = 1; + if ( !fps ) { + Debug(1, "Zero fps in updateFrameRate. Setting frame_mod=1 and effective_fps=0.0"); + effective_fps = 0.0; + return; + } + effective_fps = (base_fps*abs(replay_rate))/ZM_RATE_BASE; Debug(3, "FPS:%.2f, MXFPS:%.2f, BFPS:%.2f, EFPS:%.2f, FM:%d", fps, maxfps, base_fps, effective_fps, frame_mod); // Min frame repeat? while( effective_fps > maxfps ) { diff --git a/web/ajax/log.php b/web/ajax/log.php index fca79fda4..282303a87 100644 --- a/web/ajax/log.php +++ b/web/ajax/log.php @@ -13,7 +13,7 @@ switch ( $_REQUEST['task'] ) { $string = $_POST['message']; - $file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/\w+\//', '', $_POST['file'] ) : ''; + $file = !empty($_POST['file']) ? preg_replace( '/\w+:\/\/[\w.:]+\//', '', $_POST['file'] ) : ''; if ( !empty( $_POST['line'] ) ) $line = $_POST['line']; else diff --git a/web/ajax/status.php b/web/ajax/status.php index dbac0773b..5d8b90aa6 100644 --- a/web/ajax/status.php +++ b/web/ajax/status.php @@ -259,13 +259,14 @@ function collectData() { $index = 0; $where = array(); $values = array(); - foreach( $entitySpec['selector'] as $selector ) { + foreach( $entitySpec['selector'] as $selIndex => $selector ) { + $selectorParamName = ':selector' . $selIndex; if ( is_array( $selector ) ) { - $where[] = $selector['selector'].' = ?'; - $values[] = validInt($id[$index]); + $where[] = $selector['selector'].' = '.$selectorParamName; + $values[$selectorParamName] = validInt($id[$index]); } else { - $where[] = $selector.' = ?'; - $values[] = validInt($id[$index]); + $where[] = $selector.' = '.$selectorParamName; + $values[$selectorParamName] = validInt($id[$index]); } $index++; } @@ -273,8 +274,10 @@ function collectData() { } if ( $groupSql ) $sql .= ' GROUP BY '.join( ',', array_unique( $groupSql ) ); - if ( !empty($_REQUEST['sort']) ) - $sql .= ' order by '.$_REQUEST['sort']; + if ( !empty($_REQUEST['sort']) ) { + $sql .= ' order by :sort'; + $values[':sort'] = $_REQUEST['sort']; + } if ( !empty($entitySpec['limit']) ) $limit = $entitySpec['limit']; elseif ( !empty($_REQUEST['count']) ) diff --git a/web/includes/actions/login.php b/web/includes/actions/login.php index a6e78632d..b497b29f5 100644 --- a/web/includes/actions/login.php +++ b/web/includes/actions/login.php @@ -28,7 +28,7 @@ if ( $action == 'login' && isset($_REQUEST['username']) && ( ZM_AUTH_TYPE == 're if ( !$user ) { $view = 'login'; } else { - $view = 'console'; + $view = 'postlogin'; $redirect = ZM_BASE_URL.$_SERVER['PHP_SELF'].'?view=console'; } } diff --git a/web/includes/functions.php b/web/includes/functions.php index 8d0836d67..1a0cadc90 100644 --- a/web/includes/functions.php +++ b/web/includes/functions.php @@ -36,25 +36,37 @@ function noCacheHeaders() { } function CSPHeaders($view, $nonce) { + $additionalScriptSrc = ""; switch ($view) { + case 'login': { + if (defined('ZM_OPT_USE_GOOG_RECAPTCHA') + && defined('ZM_OPT_GOOG_RECAPTCHA_SITEKEY') + && defined('ZM_OPT_GOOG_RECAPTCHA_SECRETKEY') + && ZM_OPT_USE_GOOG_RECAPTCHA && ZM_OPT_GOOG_RECAPTCHA_SITEKEY && ZM_OPT_GOOG_RECAPTCHA_SECRETKEY) { + $additionalScriptSrc = "https://www.google.com"; + } + // fall through + } case 'bandwidth': case 'blank': + case 'console': + case 'controlcap': case 'function': case 'log': - case 'login': case 'logout': case 'options': case 'privacy': + case 'storage': case 'version': { // Enforce script-src on pages where inline scripts and event handlers have been fixed. // 'unsafe-inline' is only for backwards compatibility with browsers which // only support CSP 1 (with no nonce-* support). - header("Content-Security-Policy: script-src 'unsafe-inline' 'self' 'nonce-$nonce'"); + header("Content-Security-Policy: script-src 'unsafe-inline' 'self' 'nonce-$nonce' $additionalScriptSrc"); break; } default: { // Use Report-Only mode on all other pages. - header("Content-Security-Policy-Report-Only: script-src 'unsafe-inline' 'self' 'nonce-$nonce'"); + header("Content-Security-Policy-Report-Only: script-src 'unsafe-inline' 'self' 'nonce-$nonce' $additionalScriptSrc"); break; } } @@ -462,7 +474,7 @@ function makePopupButton( $url, $winName, $winSize, $buttonValue, $condition=1, } else { $string .= ' data-window-tag="' . htmlspecialchars($winSize) . '"'; } - if ($condition) { + if (!$condition) { $string .= ' disabled="disabled"'; } $string .= ($options ? (' ' . $options) : '') . '/>'; @@ -2434,4 +2446,8 @@ function getAffectedIds( $name ) { return $ids; } +function format_duration($time, $separator=':') { + return sprintf('%02d%s%02d%s%02d', floor($time/3600), $separator, ($time/60)%60, $separator, $time%60); +} + ?> diff --git a/web/js/Server.js b/web/js/Server.js index 73524e673..d9ab937e6 100644 --- a/web/js/Server.js +++ b/web/js/Server.js @@ -1,8 +1,20 @@ 'use strict'; -var _createClass = function() { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function(Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); +var _createClass = function() { + function defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); + } + } return function(Constructor, protoProps, staticProps) { + if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; + }; +}(); -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } +function _classCallCheck(instance, Constructor) { + if (!(instance instanceof Constructor)) { + throw new TypeError("Cannot call a class as a function"); + } +} var Server = function() { function Server(json) { diff --git a/web/js/logger.js b/web/js/logger.js index 6bd465c8a..0a1195043 100644 --- a/web/js/logger.js +++ b/web/js/logger.js @@ -17,105 +17,112 @@ // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. // -if ( !window.console ) -{ - window.console = +if ( !window.console ) { + window.console = { - init:function() {}, - log:function() {}, - debug:function() {}, - info:function() {}, - warn:function() {}, - error:function() {} + init: function() {}, + log: function() {}, + debug: function() {}, + info: function() {}, + warn: function() {}, + error: function() {} }; } -if ( !console.debug )//IE8 has console but doesn't have console.debug so lets alias it. - console.debug = console.log; +if ( !console.debug ) { + // IE8 has console but doesn't have console.debug so lets alias it. + console.debug = console.log; +} var reportLogs = true; var debugParms; var debugReq; -function logReport( level, message, file, line ) -{ - if ( !reportLogs ) - return; +function logReport( level, message, file, line ) { + if ( !reportLogs ) { + return; + } - if ( typeof(MooTools) == "undefined" ) - return; + if ( typeof(MooTools) == "undefined" ) { + return; + } + /* eslint-disable no-caller */ + if ( arguments && arguments.callee && arguments.callee.caller && arguments.callee.caller.caller && arguments.callee.caller.caller.name ) { + message += ' - '+arguments.callee.caller.caller.name+'()'; + } + /* eslint-enable no-caller */ - if ( arguments && arguments.callee && arguments.callee.caller && arguments.callee.caller.name ) - message += ' - '+arguments.callee.caller.caller.name+'()'; - - if ( !debugReq ) - { - if ( Browser ) - debugParms = "view=request&request=log&task=create&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+(Browser.Platform?Browser.Platform.name:'unknown'); - else - debugParms = "view=request&request=log&task=create&browser[name]=unknown&browser[version]=unknown&browser[platform]=unknown"; - debugReq = new Request.JSON( { url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain' } ); + if ( !debugReq ) { + if ( Browser ) { + debugParms = "view=request&request=log&task=create&browser[name]="+Browser.name+"&browser[version]="+Browser.version+"&browser[platform]="+(Browser.Platform?Browser.Platform.name:'unknown'); + } else { + debugParms = "view=request&request=log&task=create&browser[name]=unknown&browser[version]=unknown&browser[platform]=unknown"; } - var requestParms = debugParms; - requestParms += "&level="+level+"&message="+encodeURIComponent(message); - if ( file ) - requestParms += "&file="+file; - else if ( location.search ) { - //location.search is the querystring part, so ?blah=blah but there is almost never any value to this - requestParms += "&file="+location.search; - } - if ( line ) - requestParms += "&line="+line; - debugReq.send( requestParms ); + debugReq = new Request.JSON( {url: thisUrl, method: 'post', timeout: AJAX_TIMEOUT, link: 'chain'} ); + } + var requestParms = debugParms; + requestParms += "&level="+level+"&message="+encodeURIComponent(message); + if ( file ) { + requestParms += "&file="+file; + } else if ( location.search ) { + //location.search is the querystring part, so ?blah=blah but there is almost never any value to this + requestParms += "&file="+location.search; + } + if ( line ) { + requestParms += "&line="+line; + } + debugReq.send( requestParms ); } -function Panic( message ) -{ - console.error( message ); - logReport( "PNC", message ); - alert( "PANIC: "+message ); +function Panic( message ) { + console.error( message ); + logReport( "PNC", message ); + alert( "PANIC: "+message ); } -function Fatal( message ) -{ - console.error( message ); - logReport( "FAT", message ); - alert( "FATAL: "+message ); +function Fatal( message ) { + console.error( message ); + logReport( "FAT", message ); + alert( "FATAL: "+message ); } -function Error( message ) -{ - console.error( message ); - logReport( "ERR", message ); +function Error( message ) { + console.error( message ); + logReport( "ERR", message ); } -function Warning( message ) -{ - console.warn( message ); - logReport( "WAR", message ); +function Warning( message ) { + console.warn( message ); + logReport( "WAR", message ); } -function Info( message ) -{ - console.info( message ); - logReport( "INF", message ); +function Info( message ) { + console.info( message ); + logReport( "INF", message ); } -function Debug( message ) -{ - console.debug( message ); - //logReport( "DBG", message ); +function Debug( message ) { + console.debug( message ); + //logReport( "DBG", message ); } -function Dump( value, label ) -{ - if ( label ) - console.debug( label+" => " ); - console.debug( value ); +function Dump( value, label ) { + if ( label ) { + console.debug( label+" => " ); + } + console.debug( value ); } window.onerror = - function( message, url, line ) - { - logReport( "ERR", message, url, line ); + function( message, url, line ) { + logReport( "ERR", message, url, line ); }; + +window.addEventListener("securitypolicyviolation", function logCSP(evt) { + var level = evt.disposition == "enforce" ? "ERR" : "DBG"; + var message = evt.blockedURI + " violated CSP " + evt.violatedDirective; + if (evt.sample) { + message += " (Sample: " + evt.sample + ")"; + } + logReport(level, message, evt.sourceFile, evt.lineNumber); +}); diff --git a/web/js/mootools.ext.js b/web/js/mootools.ext.js index bc2f276e3..76c55fb38 100644 --- a/web/js/mootools.ext.js +++ b/web/js/mootools.ext.js @@ -6,15 +6,11 @@ var zmMooToolsVersion = '1.3.2'; /* * Firstly, lets check that mootools has been included and thus is present */ -if ( typeof(MooTools) == "undefined" ) -{ - alert( "MooTools not found! Please check that it was installed correctly in ZoneMinder web root." ); -} -else -{ - /* Version check */ - if ( MooTools.version < zmMooToolsVersion ) - { - alert( "MooTools version "+MooTools.version+" found.\nVersion "+zmMooToolsVersion+" required, please check that it was installed correctly in ZoneMinder web root." ); - } +if ( typeof(MooTools) == "undefined" ) { + alert( "MooTools not found! Please check that it was installed correctly in ZoneMinder web root." ); +} else { + /* Version check */ + if ( MooTools.version < zmMooToolsVersion ) { + alert( "MooTools version "+MooTools.version+" found.\nVersion "+zmMooToolsVersion+" required, please check that it was installed correctly in ZoneMinder web root." ); + } } diff --git a/web/js/overlay.js b/web/js/overlay.js index 9738487b0..6517d2d7d 100644 --- a/web/js/overlay.js +++ b/web/js/overlay.js @@ -1,133 +1,118 @@ var Overlay = new Class({ - Implements: [Options, Events], - initialize: function( id, options ) - { - this.setOptions( options ); + Implements: [Options, Events], + initialize: function( id, options ) { + this.setOptions( options ); - this.mask = new Mask( document.body, { 'maskMargins': false, 'class': 'overlayMask' } ); + this.mask = new Mask( document.body, {'maskMargins': false, 'class': 'overlayMask'} ); - this.id = id?id:'overlay'; - if ( typeOf(this.id) == 'string' ) - { - if ( $(this.id) ) - this.element = $(this.id); - } - else - { - this.element = this.id; - this.id = this.element.get('id'); - } - if ( !this.element ) - { - this.element = new Element( 'div', { 'id': this.id, 'class': 'overlay', 'styles': { 'display': 'none' } } ); - if ( this.options.title || this.options.buttons ) - { - var overlayHeader = new Element( 'div', { 'class': 'overlayHeader' } ); - if ( this.options.title ) - { - var overlayTitle = new Element( 'div', { 'class': 'overlayTitle', 'text': this.options.title } ); - overlayHeader.grab( overlayTitle ); - } - if ( this.options.buttons ) - { - var overlayToolbar = new Element( 'div', { 'class': 'overlayToolbar' } ); - this.options.buttons.each( - function( button ) - { - var overlayButton = new Element( 'button', { 'text': button.text } ); - if ( button.id ) - overlayButton.setProperty( 'id', button.id ); - if ( button.events ) - overlayButton.set( 'events', events ); - overlayToolbar.grab( overlayButton ); - } - ); - overlayHeader.grab( overlayTitle ); - } - this.element.grab( overlayHeader ); - var overlayBody = new Element( 'div', { 'class': 'overlayBody' } ); - var overlayContent = new Element( 'div', { 'class': 'overlayContent' } ); - overlayContent.grab( this.options.content ); - overlayBody.grab( overlayContent ); - this.element.grab( overlayBody ); - } - this.target = document.id(this.options.target) || document.id(document.body); - this.element.inject( this.target ); - } - }, - show: function() - { - this.mask.show(); - $(window).addEvent( 'resize', this.update.bind(this) ); - $(window).addEvent( 'scroll', this.update.bind(this) ); - this.element.tween( 'opacity', [0, 1.0] ); - this.element.show(); - this.element.position(); - this.mask.position(); - }, - hideComplete: function() - { - $(window).removeEvent( 'resize', this.update.bind(this) ); - $(window).removeEvent( 'scroll', this.update.bind(this) ); - this.element.hide(); - this.mask.hide(); - }, - hide: function() - { - new Fx.Tween( this.element, { duration: 400, transition: Fx.Transitions.Sine, onComplete: this.hideComplete.bind(this) } ).start( 'opacity', 1.0, 0 ); - }, - update: function() - { - this.element.position(); - this.mask.position(); - }, - showAnimation:function() - { - showOverlay(); - - //console.log( "Showing overlay loading" ); - if ( !this.loading ) - { - this.loading = new Element( 'div', { 'id': 'loading'+this.key, 'styles': { 'display':'none' } } ); - this.loading.grab( this.loadingImage ); - document.body.grab( this.loading ); - } - updateOverlayLoading(); - this.loading.setStyle( 'display', 'block' ); - $(window).addEvent( 'resize', this.update.bind(this) ); - $(window).addEvent( 'scroll', this.update.bind(this) ); - }, - hideAnimation:function() - { - $(window).removeEvent( 'resize', this.update.bind(this) ); - $(window).removeEvent( 'scroll', this.update.bind(this) ); - if ( this.loading ) - this.loading.setStyle( 'display', 'none' ); + this.id = id?id:'overlay'; + if ( typeOf(this.id) == 'string' ) { + if ( $(this.id) ) { + this.element = $(this.id); + } + } else { + this.element = this.id; + this.id = this.element.get('id'); } + if ( !this.element ) { + this.element = new Element( 'div', {'id': this.id, 'class': 'overlay', 'styles': {'display': 'none'}} ); + if ( this.options.title || this.options.buttons ) { + var overlayHeader = new Element( 'div', {'class': 'overlayHeader'} ); + if ( this.options.title ) { + var overlayTitle = new Element( 'div', {'class': 'overlayTitle', 'text': this.options.title} ); + overlayHeader.grab( overlayTitle ); + } + if ( this.options.buttons ) { + var overlayToolbar = new Element( 'div', {'class': 'overlayToolbar'} ); + this.options.buttons.each( + function( button ) { + var overlayButton = new Element( 'button', {'text': button.text} ); + if ( button.id ) { + overlayButton.setProperty( 'id', button.id ); + } + if ( button.events ) { + overlayButton.set( 'events', events ); + } + overlayToolbar.grab( overlayButton ); + } + ); + overlayHeader.grab( overlayTitle ); + } + this.element.grab( overlayHeader ); + var overlayBody = new Element( 'div', {'class': 'overlayBody'} ); + var overlayContent = new Element( 'div', {'class': 'overlayContent'} ); + overlayContent.grab( this.options.content ); + overlayBody.grab( overlayContent ); + this.element.grab( overlayBody ); + } + this.target = document.id(this.options.target) || document.id(document.body); + this.element.inject( this.target ); + } + }, + show: function() { + this.mask.show(); + window.addEventListener( 'resize', this.update.bind(this) ); + window.addEventListener( 'scroll', this.update.bind(this) ); + this.element.tween( 'opacity', [0, 1.0] ); + this.element.show(); + this.element.position(); + this.mask.position(); + }, + hideComplete: function() { + this.element.hide(); + this.mask.hide(); + }, + hide: function() { + new Fx.Tween( this.element, {duration: 400, transition: Fx.Transitions.Sine, onComplete: this.hideComplete.bind(this)} ).start( 'opacity', 1.0, 0 ); + }, + update: function() { + this.element.position(); + this.mask.position(); + }, + showAnimation: function() { + showOverlay(); + + //console.log( "Showing overlay loading" ); + if ( !this.loading ) { + this.loading = new Element( 'div', {'id': 'loading'+this.key, 'styles': {'display': 'none'}} ); + this.loading.grab( this.loadingImage ); + document.body.grab( this.loading ); + } + updateOverlayLoading(); + this.loading.setStyle( 'display', 'block' ); + window.addEventListener( 'resize', this.update.bind(this) ); + window.addEventListener( 'scroll', this.update.bind(this) ); + }, + hideAnimation: function() { + if ( this.loading ) { + this.loading.setStyle( 'display', 'none' ); + } + } }); -function setupOverlays() -{ - try { +function setupOverlays() { + try { $$('.overlay').each( - function( overlay ) - { - overlay.element = new Overlay( overlay.get('id') ); - overlay.getElements('.overlayCloser').each( - function( closer ) - { - closer.addEvent( 'click', function() { overlay.element.hide(); } ); - } - ); - overlay.overlayShow = function() { overlay.element.show(); }; - overlay.overlayHide = function() { overlay.element.hide(); }; + function( overlay ) { + overlay.element = new Overlay( overlay.get('id') ); + overlay.getElements('.overlayCloser').each( + function( closer ) { + closer.addEvent( 'click', function() { + overlay.element.hide(); + } ); + } + ); + overlay.overlayShow = function() { + overlay.element.show(); + }; + overlay.overlayHide = function() { + overlay.element.hide(); + }; } ); - } - catch ( e ) - { - alert( e ); - } + } catch ( e ) { + alert( e ); + } } -window.addEvent( 'domready', setupOverlays ); +window.addEventListener( 'DOMContentLoaded', setupOverlays ); diff --git a/web/skins/classic/includes/export_functions.php b/web/skins/classic/includes/export_functions.php index badee5822..64b3b37e0 100644 --- a/web/skins/classic/includes/export_functions.php +++ b/web/skins/classic/includes/export_functions.php @@ -293,9 +293,9 @@ function exportEventImages($event, $exportDetail, $exportFrames, $myfilelist) { * Visit http://www.dynamicdrive.com/ for full source code ***********************************************/ -var eventWidth = Width()?>; -var eventHeight = Height()?>; -var variableslide=[]; +var eventWidth = Width(); ?>; +var eventHeight = Height(); ?>; +var variableslide=[]; //configure the below 3 variables to set the dimension/background color of the slideshow diff --git a/web/skins/classic/includes/functions.php b/web/skins/classic/includes/functions.php index 535d8ba31..c5c98c8e6 100644 --- a/web/skins/classic/includes/functions.php +++ b/web/skins/classic/includes/functions.php @@ -121,11 +121,11 @@ echo output_link_if_exists( array(