Merge branch 'master' into filter_pre_post

This commit is contained in:
Isaac Connor 2020-08-24 09:23:24 -04:00
commit 0f27243007
27 changed files with 740 additions and 705 deletions

View File

@ -41,7 +41,6 @@ env:
- SMPFLAGS=-j4 OS=ubuntu DIST=xenial DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=bionic DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=disco DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=eoan DOCKER_REPO=knnniggett/packpack
- SMPFLAGS=-j4 OS=ubuntu DIST=focal DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=jessie DOCKER_REPO=iconzm/packpack
- SMPFLAGS=-j4 OS=debian DIST=stretch DOCKER_REPO=iconzm/packpack

View File

@ -1,2 +1,2 @@
/* This was done in 1.31.0 but zm_create.sql.in wasn't updated to match */
/* This was done in 1.31.0 but zm_create.sql.in wasn't updated to match. */
ALTER TABLE Monitors MODIFY LinkedMonitors varchar(255);

View File

@ -28,14 +28,18 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.35.5
Version: 1.35.6
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons
# Mootools is inder the MIT license: http://mootools.net/
# Mootools is under the MIT license: http://mootools.net/
# jQuery is under the MIT license: https://jquery.org/license/
# CakePHP is under the MIT license: https://github.com/cakephp/cakephp
# Crud is under the MIT license: https://github.com/FriendsOfCake/crud
# CakePHP-Enum-Behavior is under the MIT license: https://github.com/asper/CakePHP-Enum-Behavior
# Bootstrap is under the MIT license: https://getbootstrap.com/docs/4.5/about/license/
# Bootstrap-table is under the MIT license: https://bootstrap-table.com/docs/about/license/
# font-awesome is under CC-BY license: https://fontawesome.com/license/free
License: GPLv2+ and LGPLv2+ and MIT
URL: http://www.zoneminder.com/

View File

@ -76,39 +76,42 @@ BEGIN {
require ZoneMinder::Database;
# Process name, value pairs from the main config file first
my $config_file = ZM_CONFIG;
process_configfile($config_file);
process_configfile(ZM_CONFIG);
# Search for user created config files. If one or more are found then
# update the Config hash with those values
if ( ZM_CONFIG_SUBDIR and -d ZM_CONFIG_SUBDIR ) {
if ( -R ZM_CONFIG_SUBDIR ) {
foreach my $filename ( glob ZM_CONFIG_SUBDIR.'/*.conf' ) {
foreach my $filename (glob ZM_CONFIG_SUBDIR.'/*.conf' ) {
process_configfile($filename);
}
} else {
print( STDERR 'WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on '.ZM_CONFIG_SUBDIR.".\n" );
print(STDERR 'WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on '.ZM_CONFIG_SUBDIR.".\n");
}
}
my $dbh = ZoneMinder::Database::zmDbConnect();
die "Unable to connect to DB. ZM Cannot continue.\n" if !$dbh;
my $sql = 'SELECT Name,Value FROM Config';
my $sth = $dbh->prepare_cached($sql) or croak("Can't prepare '$sql': ".$dbh->errstr());
my $res = $sth->execute() or croak("Can't execute: ".$sth->errstr());
while( my $config = $sth->fetchrow_hashref() ) {
while ( my $config = $sth->fetchrow_hashref() ) {
# If already defined skip it because we want the values in /etc/zm.conf to override the values in Config Table
next if exists $Config{$config->{Name}};
$Config{$config->{Name}} = $config->{Value};
}
$sth->finish();
if ( ! $Config{ZM_SERVER_ID} ) {
if ( !$Config{ZM_SERVER_ID} ) {
$Config{ZM_SERVER_ID} = undef;
$sth = $dbh->prepare_cached( 'SELECT * FROM Servers WHERE Name=?' );
$sth = $dbh->prepare_cached('SELECT * FROM Servers WHERE Name=?');
if ( $Config{ZM_SERVER_NAME} ) {
$res = $sth->execute( $Config{ZM_SERVER_NAME} );
$res = $sth->execute($Config{ZM_SERVER_NAME});
my $result = $sth->fetchrow_hashref();
$Config{ZM_SERVER_ID} = $$result{Id};
} elsif ( $Config{ZM_SERVER_HOST} ) {
$res = $sth->execute( $Config{ZM_SERVER_HOST} );
$res = $sth->execute($Config{ZM_SERVER_HOST});
my $result = $sth->fetchrow_hashref();
$Config{ZM_SERVER_ID} = $$result{Id};
}
@ -126,20 +129,20 @@ require ZoneMinder::Database;
open( my $CONFIG, '<', $config_file )
or croak("Can't open config file '$config_file': $!");
foreach my $str ( <$CONFIG> ) {
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*$/ );
next if ( $str =~ /^\s*#/ );
my ( $name, $value ) = $str =~ /^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/;
if ( !$name ) {
print(STDERR "Warning, bad line in $config_file: $str\n");
next;
} # end if
$name =~ tr/a-z/A-Z/;
$name = uc $name;
#if ( !$ZoneMinder::ConfigData::options_hash{$name} ) {
#print(STDERR "Warning, unknown config option name $name in $config_file\n");
#} else {
#print(STDERR "Warning, known config option name $name in $config_file\n");
#}
$Config{$name} = $value;
#print(STDERR "Warning, unknown config option name $name in $config_file\n");
#} else {
#print(STDERR "Warning, known config option name $name in $config_file\n");
#}
$Config{$name} = $value;
} # end foreach config line
close($CONFIG);
} # end sub process_configfile
@ -147,11 +150,11 @@ require ZoneMinder::Database;
} # end BEGIN
sub loadConfigFromDB {
print( 'Loading config from DB' );
print('Loading config from DB');
my $dbh = ZoneMinder::Database::zmDbConnect();
if ( !$dbh ) {
print( "Error: unable to load options from database: $DBI::errstr\n" );
return( 0 );
print("Error: unable to load options from database: $DBI::errstr\n");
return(0);
}
my $sql = "select * from Config";
my $sth = $dbh->prepare_cached( $sql )
@ -161,13 +164,13 @@ sub loadConfigFromDB {
my $option_count = 0;
while( my $config = $sth->fetchrow_hashref() ) {
my ( $name, $value ) = ( $config->{Name}, $config->{Value} );
#print( "Name = '$name'\n" );
#print( "Name = '$name'\n" );
my $option = $options_hash{$name};
if ( !$option ) {
warn( "No option '$name' found, removing.\n" );
next;
}
#next if ( $option->{category} eq 'hidden' );
#next if ( $option->{category} eq 'hidden' );
if ( defined($value) ) {
if ( $option->{type} == $types{boolean} ) {
$option->{value} = $value?'yes':'no';
@ -204,8 +207,8 @@ sub saveConfigToDB {
my $sth = $dbh->prepare_cached( $sql )
or croak( "Can't prepare '$sql': ".$dbh->errstr() );
foreach my $option ( @options ) {
#next if ( $option->{category} eq 'hidden' );
#print( $option->{name}."\n" ) if ( !$option->{category} );
#next if ( $option->{category} eq 'hidden' );
#print( $option->{name}."\n" ) if ( !$option->{category} );
$option->{db_type} = $option->{type}->{db_type};
$option->{db_hint} = $option->{type}->{hint};
$option->{db_pattern} = $option->{type}->{pattern};

View File

@ -582,26 +582,6 @@ our @options = (
type => $types{integer},
category => 'images',
},
# Deprecated, now stream quality
{
name => 'ZM_JPEG_IMAGE_QUALITY',
default => '70',
description => q`Set the JPEG quality setting for the streamed 'live' images (1-100)`,
help => q`
When viewing a 'live' stream for a monitor ZoneMinder will grab
an image from the buffer and encode it into JPEG format before
sending it. This option specifies what image quality should be
used to encode these images. A higher number means better
quality but less compression so will take longer to view over a
slow connection. By contrast a low number means quicker to view
images but at the price of lower quality images. This option
does not apply when viewing events or still images as these are
usually just read from disk and so will be encoded at the
quality specified by the previous options.
`,
type => $types{integer},
category => 'hidden',
},
{
name => 'ZM_JPEG_STREAM_QUALITY',
default => '70',
@ -877,38 +857,6 @@ our @options = (
type => $types{integer},
category => 'config',
},
# Deprecated, really no longer necessary
{
name => 'ZM_OPT_REMOTE_CAMERAS',
default => 'no',
description => 'Are you going to use remote/networked cameras',
help => q`
ZoneMinder can work with both local cameras, ie. those attached
physically to your computer and remote or network cameras. If
you will be using networked cameras select this option.
`,
type => $types{boolean},
category => 'hidden',
},
# Deprecated, now set on a per monitor basis using the Method field
{
name => 'ZM_NETCAM_REGEXPS',
default => 'yes',
description => 'Use regular expression matching with network cameras',
help => q`
Traditionally ZoneMinder has used complex regular regular
expressions to handle the multitude of formats that network
cameras produce. In versions from 1.21.1 the default is to use
a simpler and faster built in pattern matching methodology.
This works well with most networks cameras but if you have
problems you can try the older, but more flexible, regular
expression based method by selecting this option. Note, to use
this method you must have libpcre installed on your system.
`,
requires => [ { name => 'ZM_OPT_REMOTE_CAMERAS', value => 'yes' } ],
type => $types{boolean},
category => 'hidden',
},
{
name => 'ZM_HTTP_VERSION',
default => '1.0',
@ -1974,19 +1922,6 @@ our @options = (
},
category => 'upload',
},
{
name => 'ZM_UPLOAD_FTP_HOST',
default => '',
description => 'The remote server to upload to',
help => q`
You can use filters to instruct ZoneMinder to upload events to
a remote ftp server. This option indicates the name, or ip
address, of the server to use.
`,
requires => [ { name => 'ZM_OPT_UPLOAD', value => 'yes' } ],
type => $types{hostname},
category => 'hidden',
},
{
name => 'ZM_UPLOAD_HOST',
default => '',
@ -2015,19 +1950,6 @@ our @options = (
type => $types{integer},
category => 'upload',
},
{
name => 'ZM_UPLOAD_FTP_USER',
default => '',
description => 'Your ftp username',
help => q`
You can use filters to instruct ZoneMinder to upload events to
a remote ftp server. This option indicates the username that
ZoneMinder should use to log in for ftp transfer.
`,
requires => [ { name => 'ZM_OPT_UPLOAD', value => 'yes' } ],
type => $types{alphanum},
category => 'hidden',
},
{
name => 'ZM_UPLOAD_USER',
default => '',
@ -2041,19 +1963,6 @@ our @options = (
type => $types{alphanum},
category => 'upload',
},
{
name => 'ZM_UPLOAD_FTP_PASS',
default => '',
description => 'Your ftp password',
help => q`
You can use filters to instruct ZoneMinder to upload events to
a remote ftp server. This option indicates the password that
ZoneMinder should use to log in for ftp transfer.
`,
requires => [ { name => 'ZM_OPT_UPLOAD', value => 'yes' } ],
type => $types{string},
category => 'hidden',
},
{
name => 'ZM_UPLOAD_PASS',
default => '',
@ -2069,21 +1978,6 @@ our @options = (
type => $types{string},
category => 'upload',
},
{
name => 'ZM_UPLOAD_FTP_LOC_DIR',
default => '@ZM_TMPDIR@',
description => 'The local directory in which to create upload files',
help => q`
You can use filters to instruct ZoneMinder to upload events to
a remote ftp server. This option indicates the local directory
that ZoneMinder should use for temporary upload files. These
are files that are created from events, uploaded and then
deleted.
`,
requires => [ { name => 'ZM_OPT_UPLOAD', value => 'yes' } ],
type => $types{abs_path},
category => 'hidden',
},
{
name => 'ZM_UPLOAD_LOC_DIR',
default => '@ZM_TMPDIR@',
@ -2098,19 +1992,6 @@ our @options = (
type => $types{abs_path},
category => 'upload',
},
{
name => 'ZM_UPLOAD_FTP_REM_DIR',
default => '',
description => 'The remote directory to upload to',
help => q`
You can use filters to instruct ZoneMinder to upload events to
a remote ftp server. This option indicates the remote directory
that ZoneMinder should use to upload event files to.
`,
requires => [ { name => 'ZM_OPT_UPLOAD', value => 'yes' } ],
type => $types{rel_path},
category => 'hidden',
},
{
name => 'ZM_UPLOAD_REM_DIR',
default => '',
@ -2124,21 +2005,6 @@ our @options = (
type => $types{rel_path},
category => 'upload',
},
{
name => 'ZM_UPLOAD_FTP_TIMEOUT',
default => '120',
description => 'How long to allow the transfer to take for each file',
help => q`
You can use filters to instruct ZoneMinder to upload events to
a remote ftp server. This option indicates the maximum ftp
inactivity timeout (in seconds) that should be tolerated before
ZoneMinder determines that the transfer has failed and closes
down the connection.
`,
requires => [ { name => 'ZM_OPT_UPLOAD', value => 'yes' } ],
type => $types{integer},
category => 'hidden',
},
{
name => 'ZM_UPLOAD_TIMEOUT',
default => '120',
@ -2191,20 +2057,6 @@ our @options = (
type => $types{boolean},
category => 'upload',
},
{
name => 'ZM_UPLOAD_FTP_DEBUG',
default => 'no',
description => 'Switch ftp debugging on',
help => q`
You can use filters to instruct ZoneMinder to upload events to
a remote ftp server. If you are having (or expecting) troubles
with uploading events then setting this to 'yes' permits
additional information to be included in the zmfilter log file.
`,
requires => [ { name => 'ZM_OPT_UPLOAD', value => 'yes' } ],
type => $types{boolean},
category => 'hidden',
},
{
name => 'ZM_UPLOAD_DEBUG',
default => 'no',
@ -2237,85 +2089,6 @@ our @options = (
type => $types{boolean},
category => 'mail',
},
{
name => 'ZM_EMAIL_ADDRESS',
default => '',
description => 'The email address to send matching event details to',
requires => [ { name => 'ZM_OPT_EMAIL', value => 'yes' } ],
help => q`
This option is used to define the email address that any events
that match the appropriate filters will be sent to.
`,
type => $types{email},
category => 'hidden',
},
{
name => 'ZM_EMAIL_TEXT',
default => 'subject = "ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)"
body = "
Hello,
An alarm has been detected on your installation of the ZoneMinder.
The details are as follows :-
Monitor : %MN%
Event Id : %EI%
Length : %EL%
Frames : %EF% (%EFA%)
Scores : t%EST% m%ESM% a%ESA%
This alarm was matched by the %FN% filter and can be viewed at %EPS%
ZoneMinder"',
description => 'The text of the email used to send matching event details',
requires => [ { name => 'ZM_OPT_EMAIL', value => 'yes' } ],
help => q`
This option is used to define the content of the email that is
sent for any events that match the appropriate filters.
`,
type => $types{text},
category => 'hidden',
},
{
name => 'ZM_EMAIL_SUBJECT',
default => 'ZoneMinder: Alarm - %MN%-%EI% (%ESM% - %ESA% %EFA%)',
description => 'The subject of the email used to send matching event details',
requires => [ { name => 'ZM_OPT_EMAIL', value => 'yes' } ],
help => q`
This option is used to define the subject of the email that is
sent for any events that match the appropriate filters.
`,
type => $types{string},
category => 'hidden',
},
{
name => 'ZM_EMAIL_BODY',
default => '
Hello,
An alarm has been detected on your installation of the ZoneMinder.
The details are as follows :-
Monitor : %MN%
Event Id : %EI%
Length : %EL%
Frames : %EF% (%EFA%)
Scores : t%EST% m%ESM% a%ESA%
This alarm was matched by the %FN% filter and can be viewed at %EPS%
ZoneMinder',
description => 'The body of the email used to send matching event details',
requires => [ { name => 'ZM_OPT_EMAIL', value => 'yes' } ],
help => q`
This option is used to define the content of the email that is
sent for any events that match the appropriate filters.
`,
type => $types{text},
category => 'hidden',
},
{
name => 'ZM_OPT_MESSAGE',
default => 'no',
@ -2347,19 +2120,6 @@ our @options = (
type => $types{email},
category => 'mail',
},
{
name => 'ZM_MESSAGE_TEXT',
default => 'subject = "ZoneMinder: Alarm - %MN%-%EI%"
body = "ZM alarm detected - %EL% secs, %EF%/%EFA% frames, t%EST%/m%ESM%/a%ESA% score."',
description => 'The text of the message used to send matching event details',
requires => [ { name => 'ZM_OPT_MESSAGE', value => 'yes' } ],
help => q`
This option is used to define the content of the message that
is sent for any events that match the appropriate filters.
`,
type => $types{text},
category => 'hidden',
},
{
name => 'ZM_MESSAGE_SUBJECT',
default => 'ZoneMinder: Alarm - %MN%-%EI%',
@ -2652,23 +2412,6 @@ our @options = (
category => 'config',
},
# Deprecated, superseded by event close mode
{
name => 'ZM_FORCE_CLOSE_EVENTS',
default => 'no',
description => 'Close events at section ends.',
help => q`
When a monitor is running in a continuous recording mode
(Record or Mocord) events are usually closed after a fixed
period of time (the section length). However in Mocord mode it
is possible that motion detection may occur near the end of a
section and ordinarily this will prevent the event being closed
until the motion has ceased. Switching this option on will
force the event closed at the specified time regardless of any
motion activity.
`,
type => $types{boolean},
category => 'hidden',
},
{
name => 'ZM_WEIGHTED_ALARM_CENTRES',
default => 'no',
@ -2876,34 +2619,6 @@ our @options = (
type => $types{hexadecimal},
category => 'system',
},
# Deprecated, really no longer necessary
{
name => 'ZM_WEB_REFRESH_METHOD',
default => 'javascript',
description => 'What method windows should use to refresh themselves',
help => q`
Many windows in ZoneMinder need to refresh themselves to keep
their information current. This option determines what method
they should use to do this. Choosing 'javascript' means that
each window will have a short JavaScript statement in with a
timer to prompt the refresh. This is the most compatible
method. Choosing 'http' means the refresh instruction is put in
the HTTP header. This is a cleaner method but refreshes are
interrupted or cancelled when a link in the window is clicked
meaning that the window will no longer refresh and this would
have to be done manually.
`,
type => {
db_type =>'string',
hint =>'javascript|http',
pattern =>qr|^([jh])|i,
format =>q( $1 =~ /^j/
? 'javascript'
: 'http'
)
},
category => 'hidden',
},
{
name => 'ZM_WEB_EVENT_SORT_FIELD',
default => 'DateTime',
@ -4043,7 +3758,6 @@ sub initialiseConfig {
} else {
$option->{value} = '';
}
#next if ( $option->{category} eq 'hidden' );
$option->{id} = $option_id++;
}
$configInitialised = 1;

View File

@ -36,8 +36,7 @@
void zmLoadConfig() {
// Process name, value pairs from the main config file first
char configFile[PATH_MAX] = ZM_CONFIG;
process_configfile(configFile);
process_configfile(ZM_CONFIG);
// Search for user created config files. If one or more are found then
// update the Config hash with those values

View File

@ -80,7 +80,7 @@ fi;
if [ "$DISTROS" == "" ]; then
if [ "$RELEASE" != "" ]; then
DISTROS="xenial,bionic,eoan,focal"
DISTROS="xenial,bionic,focal"
else
DISTROS=`lsb_release -a 2>/dev/null | grep Codename | awk '{print $2}'`;
fi;

View File

@ -1 +1 @@
1.35.5
1.35.6

View File

@ -31,7 +31,7 @@ global $configvals;
$configFile = ZM_CONFIG;
$localConfigFile = basename($configFile);
if ( file_exists( $localConfigFile ) && filesize( $localConfigFile ) > 0 ) {
if ( file_exists($localConfigFile) && filesize($localConfigFile) > 0 ) {
if ( php_sapi_name() == 'cli' && empty($_SERVER['REMOTE_ADDR']) )
print("Warning, overriding installed $localConfigFile file with local copy\n");
else
@ -47,15 +47,15 @@ $configvals = process_configfile($configFile);
$configSubFolder = ZM_CONFIG_SUBDIR;
if ( is_dir($configSubFolder) ) {
if ( is_readable($configSubFolder) ) {
foreach ( glob("$configSubFolder/*.conf") as $filename ) {
foreach ( glob($configSubFolder.'/*.conf') as $filename ) {
//error_log("processing $filename");
$configvals = array_replace($configvals, process_configfile($filename));
}
} else {
error_log("WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on $configSubFolder.");
error_log('WARNING: ZoneMinder configuration subfolder found but is not readable. Check folder permissions on '.$configSubFolder);
}
} else {
error_log("WARNING: ZoneMinder configuration subfolder found but is not a directory. Check $configSubFolder.");
error_log('WARNING: ZoneMinder configuration subfolder found but is not a directory. Check '.$configSubFolder);
}
# Now that our array our finalized, define each key => value
@ -67,73 +67,73 @@ foreach ( $configvals as $key => $value ) {
//
// This section is options normally derived from other options or configuration
//
define( 'ZMU_PATH', ZM_PATH_BIN.'/zmu' ); // Local path to the ZoneMinder Utility
define('ZMU_PATH', ZM_PATH_BIN.'/zmu'); // Local path to the ZoneMinder Utility
//
// If setup supports Video 4 Linux v2 and/or v1
//
define( 'ZM_HAS_V4L2', '@ZM_HAS_V4L2@' ); // V4L2 support enabled
define( 'ZM_HAS_V4L1', '@ZM_HAS_V4L1@' ); // V4L1 support enabled
define( 'ZM_HAS_V4L', '@ZM_HAS_V4L@' ); // V4L support enabled
define('ZM_HAS_V4L2', '@ZM_HAS_V4L2@'); // V4L2 support enabled
define('ZM_HAS_V4L1', '@ZM_HAS_V4L1@'); // V4L1 support enabled
define('ZM_HAS_V4L', '@ZM_HAS_V4L@'); // V4L support enabled
//
// If ONVIF support has been built in
//
define( 'ZM_HAS_ONVIF', '@ZM_HAS_ONVIF@' ); // ONVIF support enabled
define('ZM_HAS_ONVIF', '@ZM_HAS_ONVIF@'); // ONVIF support enabled
//
// If PCRE dev libraries are installed
//
define( 'ZM_PCRE', '@ZM_PCRE@' ); // PCRE support enabled
define('ZM_PCRE', '@ZM_PCRE@'); // PCRE support enabled
//
// Alarm states
//
define( 'STATE_IDLE', 0 );
define( 'STATE_PREALARM', 1 );
define( 'STATE_ALARM', 2 );
define( 'STATE_ALERT', 3 );
define( 'STATE_TAPE', 4 );
define('STATE_IDLE', 0);
define('STATE_PREALARM', 1);
define('STATE_ALARM', 2);
define('STATE_ALERT', 3);
define('STATE_TAPE', 4);
//
// DVR Control Commands
//
define( 'MSG_CMD', 1 );
define( 'MSG_DATA_WATCH', 2 );
define( 'MSG_DATA_EVENT', 3 );
define('MSG_CMD', 1);
define('MSG_DATA_WATCH', 2);
define('MSG_DATA_EVENT', 3);
define( 'CMD_NONE', 0 );
define( 'CMD_PAUSE', 1 );
define( 'CMD_PLAY', 2 );
define( 'CMD_STOP', 3 );
define( 'CMD_FASTFWD', 4 );
define( 'CMD_SLOWFWD', 5 );
define( 'CMD_SLOWREV', 6 );
define( 'CMD_FASTREV', 7 );
define( 'CMD_ZOOMIN', 8 );
define( 'CMD_ZOOMOUT', 9 );
define( 'CMD_PAN', 10 );
define( 'CMD_SCALE', 11 );
define( 'CMD_PREV', 12 );
define( 'CMD_NEXT', 13 );
define( 'CMD_SEEK', 14 );
define( 'CMD_VARPLAY', 15 );
define( 'CMD_QUIT', 17 );
define( 'CMD_QUERY', 99 );
define('CMD_NONE', 0);
define('CMD_PAUSE', 1);
define('CMD_PLAY', 2);
define('CMD_STOP', 3);
define('CMD_FASTFWD', 4);
define('CMD_SLOWFWD', 5);
define('CMD_SLOWREV', 6);
define('CMD_FASTREV', 7);
define('CMD_ZOOMIN', 8);
define('CMD_ZOOMOUT', 9);
define('CMD_PAN', 10);
define('CMD_SCALE', 11);
define('CMD_PREV', 12);
define('CMD_NEXT', 13);
define('CMD_SEEK', 14 );
define('CMD_VARPLAY', 15);
define('CMD_QUIT', 17);
define('CMD_QUERY', 99);
//
// These are miscellaneous options you won't normally need to change
//
define( 'MAX_EVENTS', 10 ); // The maximum number of events to show in the monitor event listing
define( 'RATE_BASE', 100 ); // The additional scaling factor used to help get fractional rates in integer format
define( 'SCALE_BASE', 100 ); // The additional scaling factor used to help get fractional scales in integer format
define('MAX_EVENTS', 10); // The maximum number of events to show in the monitor event listing
define('RATE_BASE', 100); // The additional scaling factor used to help get fractional rates in integer format
define('SCALE_BASE', 100); // The additional scaling factor used to help get fractional scales in integer format
//
// Date and time formats, not to be modified by language files
//
define( 'STRF_FMT_DATETIME_DB', '%Y-%m-%d %H:%M:%S' ); // Strftime format for database queries, don't change
define( 'MYSQL_FMT_DATETIME_SHORT', '%y/%m/%d %H:%i:%S' ); // MySQL date_format shorter format for dates with time
define('STRF_FMT_DATETIME_DB', '%Y-%m-%d %H:%M:%S'); // Strftime format for database queries, don't change
define('MYSQL_FMT_DATETIME_SHORT', '%y/%m/%d %H:%i:%S'); // MySQL date_format shorter format for dates with time
require_once('database.php');
require_once('logger.php');
@ -166,10 +166,18 @@ function loadConfig( $defineConsts=true ) {
if ( !$result )
echo mysql_error();
while( $row = dbFetchNext($result) ) {
if ( $defineConsts )
define($row['Name'], $row['Value']);
$config[$row['Name']] = $row;
if ( $defineConsts ) {
# Values in conf.d files override db so check if already defined and update value
if ( ! defined($row['Name']) ) {
define($row['Name'], $row['Value']);
} else {
$config[$row['Name']]['Value'] = constant($row['Name']);
}
}
}
return $config;
} # end function loadConfig
// For Human-readability, use ZM_SERVER_HOST or ZM_SERVER_NAME in zm.conf, and convert it here to a ZM_SERVER_ID
@ -197,15 +205,15 @@ if ( defined('ZM_TIMEZONE') and ZM_TIMEZONE )
ini_set('date.timezone', ZM_TIMEZONE);
function process_configfile($configFile) {
if ( is_readable( $configFile ) ) {
if ( is_readable($configFile) ) {
$configvals = array();
$cfg = fopen($configFile, 'r') or ZM\Error("Could not open config file: $configFile.");
$cfg = fopen($configFile, 'r') or ZM\Error('Could not open config file: '.$configFile);
while ( !feof($cfg) ) {
$str = fgets($cfg, 256);
if ( preg_match('/^\s*(#.*)?$/', $str) ) {
continue;
} else if ( preg_match( '/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches )) {
} else if ( preg_match('/^\s*([^=\s]+)\s*=\s*[\'"]*(.*?)[\'"]*\s*$/', $str, $matches) ) {
$configvals[$matches[1]] = $matches[2];
} else {
ZM\Error("Malformed line in config $configFile\n$str");
@ -214,7 +222,7 @@ function process_configfile($configFile) {
fclose($cfg);
return $configvals;
} else {
error_log("WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on $configFile.");
error_log('WARNING: ZoneMinder configuration file found but is not readable. Check file permissions on '.$configFile);
return false;
}
}

View File

@ -724,7 +724,11 @@ li.search-choice {
#dropdown_storage+div,
#dropdown_reminder+div,
#dropdown_bandwidth+div {
background-color:#485460;
background-color:#485460;
}
#framesTable td:hover {
cursor: pointer;
}
.zoom {
@ -738,3 +742,14 @@ background-color:#485460;
transform: scale(5); /* (arbitray zoom value - Note if the zoom is too large, it will go outside of the viewport) */
}
.zoom-right {
padding: 0px;
transition: transform .2s; /* Animation */
margin: 0 auto;
}
.zoom-right:hover {
transform-origin: 0% 50%;
transform: scale(5); /* (arbitray zoom value - Note if the zoom is too large, it will go outside of the viewport) */
}

View File

@ -132,7 +132,9 @@ if ( $css != 'base' )
<script src="skins/<?php echo $skin; ?>/js/jquery.js"></script>
<script src="skins/<?php echo $skin; ?>/js/jquery-ui-1.12.1/jquery-ui.js"></script>
<script src="skins/<?php echo $skin; ?>/js/bootstrap.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/bootstrap-table.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/bootstrap-table.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/tableExport.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/bootstrap-table-export.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/bootstrap-table-cookie.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/chosen/chosen.jquery.min.js"></script>
<script src="skins/<?php echo $skin; ?>/js/dateTimePicker/jquery-ui-timepicker-addon.js"></script>

File diff suppressed because one or more lines are too long

93
web/skins/classic/js/tableExport.min.js vendored Normal file
View File

@ -0,0 +1,93 @@
/*
tableExport.jquery.plugin
Version 1.10.20
Copyright (c) 2015-2020 hhurz, https://github.com/hhurz/tableExport.jquery.plugin
Based on https://github.com/kayalshri/tableExport.jquery.plugin
Licensed under the MIT License
*/
var $jscomp=$jscomp||{};$jscomp.scope={};$jscomp.findInternal=function(c,k,y){c instanceof String&&(c=String(c));for(var v=c.length,A=0;A<v;A++){var S=c[A];if(k.call(y,S,A,c))return{i:A,v:S}}return{i:-1,v:void 0}};$jscomp.ASSUME_ES5=!1;$jscomp.ASSUME_NO_NATIVE_MAP=!1;$jscomp.ASSUME_NO_NATIVE_SET=!1;$jscomp.defineProperty=$jscomp.ASSUME_ES5||"function"==typeof Object.defineProperties?Object.defineProperty:function(c,k,y){c!=Array.prototype&&c!=Object.prototype&&(c[k]=y.value)};
$jscomp.getGlobal=function(c){return"undefined"!=typeof window&&window===c?c:"undefined"!=typeof global&&null!=global?global:c};$jscomp.global=$jscomp.getGlobal(this);$jscomp.polyfill=function(c,k,y,v){if(k){y=$jscomp.global;c=c.split(".");for(v=0;v<c.length-1;v++){var A=c[v];A in y||(y[A]={});y=y[A]}c=c[c.length-1];v=y[c];k=k(v);k!=v&&null!=k&&$jscomp.defineProperty(y,c,{configurable:!0,writable:!0,value:k})}};
$jscomp.polyfill("Array.prototype.find",function(c){return c?c:function(c,y){return $jscomp.findInternal(this,c,y).v}},"es6","es3");
(function(c){c.fn.tableExport=function(k){function y(b){var d=[];A(b,"thead").each(function(){d.push.apply(d,A(c(this),a.theadSelector).toArray())});return d}function v(b){var d=[];A(b,"tbody").each(function(){d.push.apply(d,A(c(this),a.tbodySelector).toArray())});a.tfootSelector.length&&A(b,"tfoot").each(function(){d.push.apply(d,A(c(this),a.tfootSelector).toArray())});return d}function A(b,a){var d=b[0].tagName,p=b.parents(d).length;return b.find(a).filter(function(){return p===c(this).closest(d).parents(d).length})}
function S(b){var a=[];c(b).find("thead").first().find("th").each(function(b,d){void 0!==c(d).attr("data-field")?a[b]=c(d).attr("data-field"):a[b]=b.toString()});return a}function I(b){var a="undefined"!==typeof b[0].rowIndex,e=!1===a&&"undefined"!==typeof b[0].cellIndex,p=e||a?Ja(b):b.is(":visible"),f=b.attr("data-tableexport-display");e&&"none"!==f&&"always"!==f&&(b=c(b[0].parentNode),a="undefined"!==typeof b[0].rowIndex,f=b.attr("data-tableexport-display"));a&&"none"!==f&&"always"!==f&&(f=b.closest("table").attr("data-tableexport-display"));
return"none"!==f&&(!0===p||"always"===f)}function Ja(b){var a=[];V&&(a=J.filter(function(){var a=!1;this.nodeType===b[0].nodeType&&("undefined"!==typeof this.rowIndex&&this.rowIndex===b[0].rowIndex?a=!0:"undefined"!==typeof this.cellIndex&&this.cellIndex===b[0].cellIndex&&"undefined"!==typeof this.parentNode.rowIndex&&"undefined"!==typeof b[0].parentNode.rowIndex&&this.parentNode.rowIndex===b[0].parentNode.rowIndex&&(a=!0));return a}));return!1===V||0===a.length}function sa(b,d,e){var p=!1;I(b)?0<
a.ignoreColumn.length&&(-1!==c.inArray(e,a.ignoreColumn)||-1!==c.inArray(e-d,a.ignoreColumn)||T.length>e&&"undefined"!==typeof T[e]&&-1!==c.inArray(T[e],a.ignoreColumn))&&(p=!0):p=!0;return p}function B(b,d,e,p,f){if("function"===typeof f){var l=!1;"function"===typeof a.onIgnoreRow&&(l=a.onIgnoreRow(c(b),e));if(!1===l&&(0===a.ignoreRow.length||-1===c.inArray(e,a.ignoreRow)&&-1===c.inArray(e-p,a.ignoreRow))&&I(c(b))){var q=A(c(b),d),h=0;q.each(function(b){var a=c(this),d,l=O(this),p=U(this);c.each(G,
function(){if(e>=this.s.r&&e<=this.e.r&&h>=this.s.c&&h<=this.e.c)for(d=0;d<=this.e.c-this.s.c;++d)f(null,e,h++)});if(!1===sa(a,q.length,b)){if(p||l)l=l||1,G.push({s:{r:e,c:h},e:{r:e+(p||1)-1,c:h+l-1}});f(this,e,h++)}if(l)for(d=0;d<l-1;++d)f(null,e,h++)});c.each(G,function(){if(e>=this.s.r&&e<=this.e.r&&h>=this.s.c&&h<=this.e.c)for(da=0;da<=this.e.c-this.s.c;++da)f(null,e,h++)})}}}function ta(b,a,e,c){if("undefined"!==typeof c.images&&(e=c.images[e],"undefined"!==typeof e)){a=a.getBoundingClientRect();
var d=b.width/b.height,l=a.width/a.height,p=b.width,h=b.height,z=19.049976/25.4,g=0;l<=d?(h=Math.min(b.height,a.height),p=a.width*h/a.height):l>d&&(p=Math.min(b.width,a.width),h=a.height*p/a.width);p*=z;h*=z;h<b.height&&(g=(b.height-h)/2);try{c.doc.addImage(e.src,b.textPos.x,b.y+g,p,h)}catch(Pa){}b.textPos.x+=p}}function ua(b,d){if("string"===a.outputMode)return b.output();if("base64"===a.outputMode)return K(b.output());if("window"===a.outputMode)window.URL=window.URL||window.webkitURL,window.open(window.URL.createObjectURL(b.output("blob")));
else try{var e=b.output("blob");saveAs(e,a.fileName+".pdf")}catch(p){ja(a.fileName+".pdf","data:application/pdf"+(d?"":";base64")+",",d?b.output("blob"):b.output())}}function va(b,a,e){var d=0;"undefined"!==typeof e&&(d=e.colspan);if(0<=d){for(var c=b.width,l=b.textPos.x,q=a.table.columns.indexOf(a.column),h=1;h<d;h++)c+=a.table.columns[q+h].width;1<d&&("right"===b.styles.halign?l=b.textPos.x+c-b.width:"center"===b.styles.halign&&(l=b.textPos.x+(c-b.width)/2));b.width=c;b.textPos.x=l;"undefined"!==
typeof e&&1<e.rowspan&&(b.height*=e.rowspan);if("middle"===b.styles.valign||"bottom"===b.styles.valign)e=("string"===typeof b.text?b.text.split(/\r\n|\r|\n/g):b.text).length||1,2<e&&(b.textPos.y-=(2-1.15)/2*a.row.styles.fontSize*(e-2)/3);return!0}return!1}function wa(b,a,e){"undefined"!==typeof b&&null!==b&&(b.hasAttribute("data-tableexport-canvas")?(a=(new Date).getTime(),c(b).attr("data-tableexport-canvas",a),e.images[a]={url:'[data-tableexport-canvas="'+a+'"]',src:null}):"undefined"!==a&&null!=
a&&a.each(function(){if(c(this).is("img")){var a=xa(this.src);e.images[a]={url:this.src,src:this.src}}wa(b,c(this).children(),e)}))}function Ka(b,a){function d(b){if(b.url)if(b.src){var d=new Image;p=++f;d.crossOrigin="Anonymous";d.onerror=d.onload=function(){if(d.complete&&(0===d.src.indexOf("data:image/")&&(d.width=b.width||d.width||0,d.height=b.height||d.height||0),d.width+d.height)){var e=document.createElement("canvas"),c=e.getContext("2d");e.width=d.width;e.height=d.height;c.drawImage(d,0,0);
b.src=e.toDataURL("image/png")}--f||a(p)};d.src=b.url}else{var e=c(b.url);e.length&&(p=++f,html2canvas(e[0]).then(function(d){b.src=d.toDataURL("image/png");--f||a(p)}))}}var p=0,f=0;if("undefined"!==typeof b.images)for(var l in b.images)b.images.hasOwnProperty(l)&&d(b.images[l]);(b=f)||(a(p),b=void 0);return b}function ya(b,d,e){d.each(function(){if(c(this).is("div")){var d=ea(L(this,"background-color"),[255,255,255]),f=ea(L(this,"border-top-color"),[0,0,0]),l=fa(this,"border-top-width",a.jspdf.unit),
q=this.getBoundingClientRect(),h=this.offsetLeft*e.wScaleFactor,z=this.offsetTop*e.hScaleFactor,g=q.width*e.wScaleFactor;q=q.height*e.hScaleFactor;e.doc.setDrawColor.apply(void 0,f);e.doc.setFillColor.apply(void 0,d);e.doc.setLineWidth(l);e.doc.rect(b.x+h,b.y+z,g,q,l?"FD":"F")}else c(this).is("img")&&(d=xa(this.src),ta(b,this,d,e));ya(b,c(this).children(),e)})}function za(b,d,e){if("function"===typeof e.onAutotableText)e.onAutotableText(e.doc,b,d);else{var p=b.textPos.x,f=b.textPos.y,l={halign:b.styles.halign,
valign:b.styles.valign};if(d.length){for(d=d[0];d.previousSibling;)d=d.previousSibling;for(var q=!1,h=!1;d;){var z=d.innerText||d.textContent||"",g=z.length&&" "===z[0]?" ":"",k=1<z.length&&" "===z[z.length-1]?" ":"";!0!==a.preserve.leadingWS&&(z=g+ka(z));!0!==a.preserve.trailingWS&&(z=la(z)+k);c(d).is("br")&&(p=b.textPos.x,f+=e.doc.internal.getFontSize());c(d).is("b")?q=!0:c(d).is("i")&&(h=!0);(q||h)&&e.doc.setFontType(q&&h?"bolditalic":q?"bold":"italic");if(g=e.doc.getStringUnitWidth(z)*e.doc.internal.getFontSize()){"linebreak"===
b.styles.overflow&&p>b.textPos.x&&p+g>b.textPos.x+b.width&&(0<=".,!%*;:=-".indexOf(z.charAt(0))&&(k=z.charAt(0),g=e.doc.getStringUnitWidth(k)*e.doc.internal.getFontSize(),p+g<=b.textPos.x+b.width&&(e.doc.autoTableText(k,p,f,l),z=z.substring(1,z.length)),g=e.doc.getStringUnitWidth(z)*e.doc.internal.getFontSize()),p=b.textPos.x,f+=e.doc.internal.getFontSize());if("visible"!==b.styles.overflow)for(;z.length&&p+g>b.textPos.x+b.width;)z=z.substring(0,z.length-1),g=e.doc.getStringUnitWidth(z)*e.doc.internal.getFontSize();
e.doc.autoTableText(z,p,f,l);p+=g}if(q||h)c(d).is("b")?q=!1:c(d).is("i")&&(h=!1),e.doc.setFontType(q||h?q?"bold":"italic":"normal");d=d.nextSibling}b.textPos.x=p;b.textPos.y=f}else e.doc.autoTableText(b.text,b.textPos.x,b.textPos.y,l)}}function W(b,a,e){return null==b?"":b.toString().replace(new RegExp(null==a?"":a.toString().replace(/([.*+?^=!:${}()|\[\]\/\\])/g,"\\$1"),"g"),e)}function ka(b){return null==b?"":b.toString().replace(/^\s+/,"")}function la(b){return null==b?"":b.toString().replace(/\s+$/,
"")}function La(b){if(0===a.date.html.length)return!1;a.date.pattern.lastIndex=0;var d=a.date.pattern.exec(b);if(null==d)return!1;b=+d[a.date.match_y];if(0>b||8099<b)return!1;var e=1*d[a.date.match_m];d=1*d[a.date.match_d];if(!isFinite(d))return!1;var c=new Date(b,e-1,d,0,0,0);return c.getFullYear()===b&&c.getMonth()===e-1&&c.getDate()===d?new Date(Date.UTC(b,e-1,d,0,0,0)):!1}function ma(b){b=b||"0";""!==a.numbers.html.thousandsSeparator&&(b=W(b,a.numbers.html.thousandsSeparator,""));"."!==a.numbers.html.decimalMark&&
(b=W(b,a.numbers.html.decimalMark,"."));return"number"===typeof b||!1!==jQuery.isNumeric(b)?b:!1}function Ma(b){-1<b.indexOf("%")?(b=ma(b.replace(/%/g,"")),!1!==b&&(b/=100)):b=!1;return b}function E(b,d,e,p){var f="",l="text";if(null!==b){var q=c(b);q.removeData("teUserDefText");if(q[0].hasAttribute("data-tableexport-canvas"))var h="";else if(q[0].hasAttribute("data-tableexport-value"))h=(h=q.attr("data-tableexport-value"))?h+"":"",q.data("teUserDefText",1);else if(h=q.html(),"function"===typeof a.onCellHtmlData)h=
a.onCellHtmlData(q,d,e,h),q.data("teUserDefText",1);else if(""!==h){b=c.parseHTML(h);var g=0,k=0;h="";c.each(b,function(){if(c(this).is("input"))h+=q.find("input").eq(g++).val();else if(c(this).is("select"))h+=q.find("select option:selected").eq(k++).text();else if(c(this).is("br"))h+="<br>";else{if("undefined"===typeof c(this).html())h+=c(this).text();else if(void 0===jQuery().bootstrapTable||!1===c(this).hasClass("fht-cell")&&!1===c(this).hasClass("filterControl")&&0===q.parents(".detail-view").length)h+=
c(this).html();if(c(this).is("a")){var b=q.find("a").attr("href")||"";f="function"===typeof a.onCellHtmlHyperlink?f+a.onCellHtmlHyperlink(q,d,e,b,h):"href"===a.htmlHyperlink?f+b:f+h;h=""}}})}if(h&&""!==h&&!0===a.htmlContent)f=c.trim(h);else if(h&&""!==h)if(""!==q.attr("data-tableexport-cellformat")){var m=h.replace(/\n/g,"\u2028").replace(/(<\s*br([^>]*)>)/gi,"\u2060"),n=c("<div/>").html(m).contents();b=!1;m="";c.each(n.text().split("\u2028"),function(b,d){0<b&&(m+=" ");!0!==a.preserve.leadingWS&&
(d=ka(d));m+=!0!==a.preserve.trailingWS?la(d):d});c.each(m.split("\u2060"),function(b,d){0<b&&(f+="\n");!0!==a.preserve.leadingWS&&(d=ka(d));!0!==a.preserve.trailingWS&&(d=la(d));f+=d.replace(/\u00AD/g,"")});f=f.replace(/\u00A0/g," ");if("json"===a.type||"excel"===a.type&&"xmlss"===a.mso.fileFormat||!1===a.numbers.output)b=ma(f),!1!==b&&(l="number",f=Number(b));else if(a.numbers.html.decimalMark!==a.numbers.output.decimalMark||a.numbers.html.thousandsSeparator!==a.numbers.output.thousandsSeparator)if(b=
ma(f),!1!==b){n=(""+b.substr(0>b?1:0)).split(".");1===n.length&&(n[1]="");var t=3<n[0].length?n[0].length%3:0;l="number";f=(0>b?"-":"")+(a.numbers.output.thousandsSeparator?(t?n[0].substr(0,t)+a.numbers.output.thousandsSeparator:"")+n[0].substr(t).replace(/(\d{3})(?=\d)/g,"$1"+a.numbers.output.thousandsSeparator):n[0])+(n[1].length?a.numbers.output.decimalMark+n[1]:"")}}else f=h;!0===a.escape&&(f=escape(f));"function"===typeof a.onCellData&&(f=a.onCellData(q,d,e,f,l),q.data("teUserDefText",1))}void 0!==
p&&(p.type=l);return f}function Aa(b){return 0<b.length&&!0===a.preventInjection&&0<="=+-@".indexOf(b.charAt(0))?"'"+b:b}function Na(b,a,e){return a+"-"+e.toLowerCase()}function ea(b,a){(b=/^rgb\((\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\)$/.exec(b))&&(a=[parseInt(b[1]),parseInt(b[2]),parseInt(b[3])]);return a}function Ba(b){var a=L(b,"text-align"),e=L(b,"font-weight"),c=L(b,"font-style"),f="";"start"===a&&(a="rtl"===L(b,"direction")?"right":"left");700<=e&&(f="bold");"italic"===c&&(f+=c);""===f&&(f="normal");
a={style:{align:a,bcolor:ea(L(b,"background-color"),[255,255,255]),color:ea(L(b,"color"),[0,0,0]),fstyle:f},colspan:O(b),rowspan:U(b)};null!==b&&(b=b.getBoundingClientRect(),a.rect={width:b.width,height:b.height});return a}function O(b){var a=c(b).attr("data-tableexport-colspan");"undefined"===typeof a&&c(b).is("[colspan]")&&(a=c(b).attr("colspan"));return parseInt(a)||0}function U(b){var a=c(b).attr("data-tableexport-rowspan");"undefined"===typeof a&&c(b).is("[rowspan]")&&(a=c(b).attr("rowspan"));
return parseInt(a)||0}function L(b,a){try{return window.getComputedStyle?(a=a.replace(/([a-z])([A-Z])/,Na),window.getComputedStyle(b,null).getPropertyValue(a)):b.currentStyle?b.currentStyle[a]:b.style[a]}catch(e){}return""}function fa(a,d,e){d=L(a,d).match(/\d+/);if(null!==d){d=d[0];a=a.parentElement;var b=document.createElement("div");b.style.overflow="hidden";b.style.visibility="hidden";a.appendChild(b);b.style.width=100+e;e=100/b.offsetWidth;a.removeChild(b);return d*e}return 0}function Oa(a){for(var b=
new ArrayBuffer(a.length),e=new Uint8Array(b),c=0;c!==a.length;++c)e[c]=a.charCodeAt(c)&255;return b}function na(a){var b=a.c,c="";for(++b;b;b=Math.floor((b-1)/26))c=String.fromCharCode((b-1)%26+65)+c;return c+(""+(a.r+1))}function oa(a,d){if("undefined"===typeof d||"number"===typeof d)return oa(a.s,a.e);"string"!==typeof a&&(a=na(a));"string"!==typeof d&&(d=na(d));return a===d?a:a+":"+d}function Ca(a,d){var b=Number(a);if(isFinite(b))return b;var c=1;""!==d.thousandsSeparator&&(a=a.replace(new RegExp("([\\d])"+
d.thousandsSeparator+"([\\d])","g"),"$1$2"));"."!==d.decimalMark&&(a=a.replace(new RegExp("([\\d])"+d.decimalMark+"([\\d])","g"),"$1.$2"));a=a.replace(/[$]/g,"").replace(/[%]/g,function(){c*=100;return""});if(isFinite(b=Number(a)))return b/c;a=a.replace(/[(](.*)[)]/,function(a,b){c=-c;return b});return isFinite(b=Number(a))?b/c:b}function xa(a){var b=0,c;if(0===a.length)return b;var p=0;for(c=a.length;p<c;p++){var f=a.charCodeAt(p);b=(b<<5)-b+f;b|=0}return b}function M(b,d,c,p,f,l){var e=!0;"function"===
typeof a.onBeforeSaveToFile&&(e=a.onBeforeSaveToFile(b,d,c,p,f),"boolean"!==typeof e&&(e=!0));if(e)try{if(Da=new Blob([b],{type:c+";charset="+p}),saveAs(Da,d,!1===l),"function"===typeof a.onAfterSaveToFile)a.onAfterSaveToFile(b,d)}catch(h){ja(d,"data:"+c+(p.length?";charset="+p:"")+(f.length?";"+f:"")+",",l?"\ufeff"+b:b)}}function ja(b,d,c){var e=window.navigator.userAgent;if(!1!==b&&window.navigator.msSaveOrOpenBlob)window.navigator.msSaveOrOpenBlob(new Blob([c]),b);else if(!1!==b&&(0<e.indexOf("MSIE ")||
e.match(/Trident.*rv\:11\./))){if(d=document.createElement("iframe")){document.body.appendChild(d);d.setAttribute("style","display:none");d.contentDocument.open("txt/plain","replace");d.contentDocument.write(c);d.contentDocument.close();d.contentWindow.focus();switch(b.substr(b.lastIndexOf(".")+1)){case "doc":case "json":case "png":case "pdf":case "xls":case "xlsx":b+=".txt"}d.contentDocument.execCommand("SaveAs",!0,b);document.body.removeChild(d)}}else{var f=document.createElement("a");if(f){var l=
null;f.style.display="none";!1!==b?f.download=b:f.target="_blank";"object"===typeof c?(window.URL=window.URL||window.webkitURL,e=[],e.push(c),l=window.URL.createObjectURL(new Blob(e,{type:d})),f.href=l):0<=d.toLowerCase().indexOf("base64,")?f.href=d+K(c):f.href=d+encodeURIComponent(c);document.body.appendChild(f);if(document.createEvent)null===ha&&(ha=document.createEvent("MouseEvents")),ha.initEvent("click",!0,!1),f.dispatchEvent(ha);else if(document.createEventObject)f.fireEvent("onclick");else if("function"===
typeof f.onclick)f.onclick();setTimeout(function(){l&&window.URL.revokeObjectURL(l);document.body.removeChild(f);if("function"===typeof a.onAfterSaveToFile)a.onAfterSaveToFile(c,b)},100)}}}function K(a){var b,c="",p=0;if("string"===typeof a){a=a.replace(/\x0d\x0a/g,"\n");var f="";for(b=0;b<a.length;b++){var l=a.charCodeAt(b);128>l?f+=String.fromCharCode(l):(127<l&&2048>l?f+=String.fromCharCode(l>>6|192):(f+=String.fromCharCode(l>>12|224),f+=String.fromCharCode(l>>6&63|128)),f+=String.fromCharCode(l&
63|128))}a=f}for(;p<a.length;){var q=a.charCodeAt(p++);f=a.charCodeAt(p++);b=a.charCodeAt(p++);l=q>>2;q=(q&3)<<4|f>>4;var h=(f&15)<<2|b>>6;var g=b&63;isNaN(f)?h=g=64:isNaN(b)&&(g=64);c=c+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(l)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(q)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(h)+"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=".charAt(g)}return c}
var a={csvEnclosure:'"',csvSeparator:",",csvUseBOM:!0,date:{html:"dd/mm/yyyy"},displayTableName:!1,escape:!1,exportHiddenCells:!1,fileName:"tableExport",htmlContent:!1,htmlHyperlink:"content",ignoreColumn:[],ignoreRow:[],jsonScope:"all",jspdf:{orientation:"p",unit:"pt",format:"a4",margins:{left:20,right:10,top:10,bottom:10},onDocCreated:null,autotable:{styles:{cellPadding:2,rowHeight:12,fontSize:8,fillColor:255,textColor:50,fontStyle:"normal",overflow:"ellipsize",halign:"inherit",valign:"middle"},
headerStyles:{fillColor:[52,73,94],textColor:255,fontStyle:"bold",halign:"inherit",valign:"middle"},alternateRowStyles:{fillColor:245},tableExport:{doc:null,onAfterAutotable:null,onBeforeAutotable:null,onAutotableText:null,onTable:null,outputImages:!0}}},mso:{fileFormat:"xlshtml",onMsoNumberFormat:null,pageFormat:"a4",pageOrientation:"portrait",rtl:!1,styles:[],worksheetName:"",xslx:{formatId:{date:14,numbers:2}}},numbers:{html:{decimalMark:".",thousandsSeparator:","},output:{decimalMark:".",thousandsSeparator:","}},
onAfterSaveToFile:null,onBeforeSaveToFile:null,onCellData:null,onCellHtmlData:null,onCellHtmlHyperlink:null,onIgnoreRow:null,onTableExportBegin:null,onTableExportEnd:null,outputMode:"file",pdfmake:{enabled:!1,docDefinition:{pageOrientation:"portrait",defaultStyle:{font:"Roboto"}},fonts:{}},preserve:{leadingWS:!1,trailingWS:!1},preventInjection:!0,sql:{tableEnclosure:"`",columnEnclosure:"`"},tbodySelector:"tr",tfootSelector:"tr",theadSelector:"tr",tableName:"Table",type:"csv"},N={a0:[2383.94,3370.39],
a1:[1683.78,2383.94],a2:[1190.55,1683.78],a3:[841.89,1190.55],a4:[595.28,841.89],a5:[419.53,595.28],a6:[297.64,419.53],a7:[209.76,297.64],a8:[147.4,209.76],a9:[104.88,147.4],a10:[73.7,104.88],b0:[2834.65,4008.19],b1:[2004.09,2834.65],b2:[1417.32,2004.09],b3:[1000.63,1417.32],b4:[708.66,1000.63],b5:[498.9,708.66],b6:[354.33,498.9],b7:[249.45,354.33],b8:[175.75,249.45],b9:[124.72,175.75],b10:[87.87,124.72],c0:[2599.37,3676.54],c1:[1836.85,2599.37],c2:[1298.27,1836.85],c3:[918.43,1298.27],c4:[649.13,
918.43],c5:[459.21,649.13],c6:[323.15,459.21],c7:[229.61,323.15],c8:[161.57,229.61],c9:[113.39,161.57],c10:[79.37,113.39],dl:[311.81,623.62],letter:[612,792],"government-letter":[576,756],legal:[612,1008],"junior-legal":[576,360],ledger:[1224,792],tabloid:[792,1224],"credit-card":[153,243]},C=this,ha=null,u=[],w=[],n=0,t="",T=[],G=[],Da,J=[],V=!1;c.extend(!0,a,k);"xlsx"===a.type&&(a.mso.fileFormat=a.type,a.type="excel");"undefined"!==typeof a.excelFileFormat&&"undefined"===a.mso.fileFormat&&(a.mso.fileFormat=
a.excelFileFormat);"undefined"!==typeof a.excelPageFormat&&"undefined"===a.mso.pageFormat&&(a.mso.pageFormat=a.excelPageFormat);"undefined"!==typeof a.excelPageOrientation&&"undefined"===a.mso.pageOrientation&&(a.mso.pageOrientation=a.excelPageOrientation);"undefined"!==typeof a.excelRTL&&"undefined"===a.mso.rtl&&(a.mso.rtl=a.excelRTL);"undefined"!==typeof a.excelstyles&&"undefined"===a.mso.styles&&(a.mso.styles=a.excelstyles);"undefined"!==typeof a.onMsoNumberFormat&&"undefined"===a.mso.onMsoNumberFormat&&
(a.mso.onMsoNumberFormat=a.onMsoNumberFormat);"undefined"!==typeof a.worksheetName&&"undefined"===a.mso.worksheetName&&(a.mso.worksheetName=a.worksheetName);a.mso.pageOrientation="l"===a.mso.pageOrientation.substr(0,1)?"landscape":"portrait";a.date.html=a.date.html||"";if(a.date.html.length){k=[];k.dd="(3[01]|[12][0-9]|0?[1-9])";k.mm="(1[012]|0?[1-9])";k.yyyy="((?:1[6-9]|2[0-2])\\d{2})";k.yy="(\\d{2})";var r=a.date.html.match(/[^a-zA-Z0-9]/)[0];r=a.date.html.toLowerCase().split(r);a.date.regex="^\\s*";
a.date.regex+=k[r[0]];a.date.regex+="(.)";a.date.regex+=k[r[1]];a.date.regex+="\\2";a.date.regex+=k[r[2]];a.date.regex+="\\s*$";a.date.pattern=new RegExp(a.date.regex,"g");k=r.indexOf("dd")+1;a.date.match_d=k+(1<k?1:0);k=r.indexOf("mm")+1;a.date.match_m=k+(1<k?1:0);k=(0<=r.indexOf("yyyy")?r.indexOf("yyyy"):r.indexOf("yy"))+1;a.date.match_y=k+(1<k?1:0)}T=S(C);if("function"===typeof a.onTableExportBegin)a.onTableExportBegin();if("csv"===a.type||"tsv"===a.type||"txt"===a.type){var P="",Z=0;G=[];n=0;
var pa=function(b,d,e){b.each(function(){t="";B(this,d,n,e+b.length,function(b,c,d){var e=t,f="";if(null!==b)if(b=E(b,c,d),c=null===b||""===b?"":b.toString(),"tsv"===a.type)b instanceof Date&&b.toLocaleString(),f=W(c,"\t"," ");else if(b instanceof Date)f=a.csvEnclosure+b.toLocaleString()+a.csvEnclosure;else if(f=Aa(c),f=W(f,a.csvEnclosure,a.csvEnclosure+a.csvEnclosure),0<=f.indexOf(a.csvSeparator)||/[\r\n ]/g.test(f))f=a.csvEnclosure+f+a.csvEnclosure;t=e+(f+("tsv"===a.type?"\t":a.csvSeparator))});
t=c.trim(t).substring(0,t.length-1);0<t.length&&(0<P.length&&(P+="\n"),P+=t);n++});return b.length};Z+=pa(c(C).find("thead").first().find(a.theadSelector),"th,td",Z);A(c(C),"tbody").each(function(){Z+=pa(A(c(this),a.tbodySelector),"td,th",Z)});a.tfootSelector.length&&pa(c(C).find("tfoot").first().find(a.tfootSelector),"td,th",Z);P+="\n";if("string"===a.outputMode)return P;if("base64"===a.outputMode)return K(P);if("window"===a.outputMode){ja(!1,"data:text/"+("csv"===a.type?"csv":"plain")+";charset=utf-8,",
P);return}M(P,a.fileName+"."+a.type,"text/"+("csv"===a.type?"csv":"plain"),"utf-8","","csv"===a.type&&a.csvUseBOM)}else if("sql"===a.type){n=0;G=[];var D="INSERT INTO "+a.sql.tableEnclosure+a.tableName+a.sql.tableEnclosure+" (";u=y(c(C));c(u).each(function(){B(this,"th,td",n,u.length,function(b,c,e){b=E(b,c,e)||"";-1<b.indexOf(a.sql.columnEnclosure)&&(b=W(b.toString(),a.sql.columnEnclosure,a.sql.columnEnclosure+a.sql.columnEnclosure));D+=a.sql.columnEnclosure+b+a.sql.columnEnclosure+","});n++;D=c.trim(D).substring(0,
D.length-1)});D+=") VALUES ";w=v(c(C));c(w).each(function(){t="";B(this,"td,th",n,u.length+w.length,function(a,c,e){a=E(a,c,e)||"";-1<a.indexOf("'")&&(a=W(a.toString(),"'","''"));t+="'"+a+"',"});3<t.length&&(D+="("+t,D=c.trim(D).substring(0,D.length-1),D+="),");n++});D=c.trim(D).substring(0,D.length-1);D+=";";if("string"===a.outputMode)return D;if("base64"===a.outputMode)return K(D);M(D,a.fileName+".sql","application/sql","utf-8","",!1)}else if("json"===a.type){var X=[];G=[];u=y(c(C));c(u).each(function(){var a=
[];B(this,"th,td",n,u.length,function(b,c,g){a.push(E(b,c,g))});X.push(a)});var qa=[];w=v(c(C));c(w).each(function(){var a={},d=0;B(this,"td,th",n,u.length+w.length,function(b,c,f){X.length?a[X[X.length-1][d]]=E(b,c,f):a[d]=E(b,c,f);d++});!1===c.isEmptyObject(a)&&qa.push(a);n++});k="head"===a.jsonScope?JSON.stringify(X):"data"===a.jsonScope?JSON.stringify(qa):JSON.stringify({header:X,data:qa});if("string"===a.outputMode)return k;if("base64"===a.outputMode)return K(k);M(k,a.fileName+".json","application/json",
"utf-8","base64",!1)}else if("xml"===a.type){n=0;G=[];var Q='<?xml version="1.0" encoding="utf-8"?>';Q+="<tabledata><fields>";u=y(c(C));c(u).each(function(){B(this,"th,td",n,u.length,function(a,c,e){Q+="<field>"+E(a,c,e)+"</field>"});n++});Q+="</fields><data>";var Ea=1;w=v(c(C));c(w).each(function(){var a=1;t="";B(this,"td,th",n,u.length+w.length,function(b,c,g){t+="<column-"+a+">"+E(b,c,g)+"</column-"+a+">";a++});0<t.length&&"<column-1></column-1>"!==t&&(Q+='<row id="'+Ea+'">'+t+"</row>",Ea++);n++});
Q+="</data></tabledata>";if("string"===a.outputMode)return Q;if("base64"===a.outputMode)return K(Q);M(Q,a.fileName+".xml","application/xml","utf-8","base64",!1)}else if("excel"===a.type&&"xmlss"===a.mso.fileFormat){var ra=[],F=[];c(C).filter(function(){return I(c(this))}).each(function(){function b(a,b,d){var f=[];c(a).each(function(){var b=0,e=0;t="";B(this,"td,th",n,d+a.length,function(a,d,l){if(null!==a){var h="";d=E(a,d,l);l="String";if(!1!==jQuery.isNumeric(d))l="Number";else{var g=Ma(d);!1!==
g&&(d=g,l="Number",h+=' ss:StyleID="pct1"')}"Number"!==l&&(d=d.replace(/\n/g,"<br>"));g=O(a);a=U(a);c.each(f,function(){if(n>=this.s.r&&n<=this.e.r&&e>=this.s.c&&e<=this.e.c)for(var a=0;a<=this.e.c-this.s.c;++a)e++,b++});if(a||g)a=a||1,g=g||1,f.push({s:{r:n,c:e},e:{r:n+a-1,c:e+g-1}});1<g&&(h+=' ss:MergeAcross="'+(g-1)+'"',e+=g-1);1<a&&(h+=' ss:MergeDown="'+(a-1)+'" ss:StyleID="rsp1"');0<b&&(h+=' ss:Index="'+(e+1)+'"',b=0);t+="<Cell"+h+'><Data ss:Type="'+l+'">'+c("<div />").text(d).html()+"</Data></Cell>\r";
e++}});0<t.length&&(H+='<Row ss:AutoFitHeight="0">\r'+t+"</Row>\r");n++});return a.length}var d=c(this),e="";"string"===typeof a.mso.worksheetName&&a.mso.worksheetName.length?e=a.mso.worksheetName+" "+(F.length+1):"undefined"!==typeof a.mso.worksheetName[F.length]&&(e=a.mso.worksheetName[F.length]);e.length||(e=d.find("caption").text()||"");e.length||(e="Table "+(F.length+1));e=c.trim(e.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31));F.push(c("<div />").text(e).html());!1===a.exportHiddenCells&&(J=
d.find("tr, th, td").filter(":hidden"),V=0<J.length);n=0;T=S(this);H="<Table>\r";e=b(y(d),"th,td",0);b(v(d),"td,th",e);H+="</Table>\r";ra.push(H)});k={};r={};for(var m,R,Y=0,da=F.length;Y<da;Y++)m=F[Y],R=k[m],R=k[m]=null==R?1:R+1,2===R&&(F[r[m]]=F[r[m]].substring(0,29)+"-1"),1<k[m]?F[Y]=F[Y].substring(0,29)+"-"+k[m]:r[m]=Y;k='<?xml version="1.0" encoding="UTF-8"?>\r<?mso-application progid="Excel.Sheet"?>\r<Workbook xmlns="urn:schemas-microsoft-com:office:spreadsheet"\r xmlns:o="urn:schemas-microsoft-com:office:office"\r xmlns:x="urn:schemas-microsoft-com:office:excel"\r xmlns:ss="urn:schemas-microsoft-com:office:spreadsheet"\r xmlns:html="http://www.w3.org/TR/REC-html40">\r<DocumentProperties xmlns="urn:schemas-microsoft-com:office:office">\r <Created>'+
(new Date).toISOString()+'</Created>\r</DocumentProperties>\r<OfficeDocumentSettings xmlns="urn:schemas-microsoft-com:office:office">\r <AllowPNG/>\r</OfficeDocumentSettings>\r<ExcelWorkbook xmlns="urn:schemas-microsoft-com:office:excel">\r <WindowHeight>9000</WindowHeight>\r <WindowWidth>13860</WindowWidth>\r <WindowTopX>0</WindowTopX>\r <WindowTopY>0</WindowTopY>\r <ProtectStructure>False</ProtectStructure>\r <ProtectWindows>False</ProtectWindows>\r</ExcelWorkbook>\r<Styles>\r <Style ss:ID="Default" ss:Name="Normal">\r <Alignment ss:Vertical="Bottom"/>\r <Borders/>\r <Font/>\r <Interior/>\r <NumberFormat/>\r <Protection/>\r </Style>\r <Style ss:ID="rsp1">\r <Alignment ss:Vertical="Center"/>\r </Style>\r <Style ss:ID="pct1">\r <NumberFormat ss:Format="Percent"/>\r </Style>\r</Styles>\r';
for(r=0;r<ra.length;r++)k+='<Worksheet ss:Name="'+F[r]+'" ss:RightToLeft="'+(a.mso.rtl?"1":"0")+'">\r'+ra[r],k=a.mso.rtl?k+'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel">\r<DisplayRightToLeft/>\r</WorksheetOptions>\r':k+'<WorksheetOptions xmlns="urn:schemas-microsoft-com:office:excel"/>\r',k+="</Worksheet>\r";k+="</Workbook>\r";if("string"===a.outputMode)return k;if("base64"===a.outputMode)return K(k);M(k,a.fileName+".xml","application/xml","utf-8","base64",!1)}else if("excel"===
a.type&&"xlsx"===a.mso.fileFormat){var aa=[],Fa=XLSX.utils.book_new();c(C).filter(function(){return I(c(this))}).each(function(){for(var b=c(this),d={},e=this.getElementsByTagName("tr"),g={s:{r:0,c:0},e:{r:0,c:0}},f=[],l,q=[],h=0,k=0,m,n,t,u,r,w=XLSX.SSF.get_table();h<e.length&&1E7>k;++h)if(m=e[h],n=!1,"function"===typeof a.onIgnoreRow&&(n=a.onIgnoreRow(c(m),h)),!0!==n&&(0===a.ignoreRow.length||-1===c.inArray(h,a.ignoreRow)&&-1===c.inArray(h-e.length,a.ignoreRow))&&!1!==I(c(m))){var y=m.children,
C=0;for(m=0;m<y.length;++m)r=y[m],u=+O(r)||1,C+=u;var A=0;for(m=n=0;m<y.length;++m)if(r=y[m],u=+O(r)||1,l=m+A,!sa(c(r),C,l+(l<n?n-l:0))){A+=u-1;for(l=0;l<f.length;++l){var v=f[l];v.s.c==n&&v.s.r<=k&&k<=v.e.r&&(n=v.e.c+1,l=-1)}(0<(t=+U(r))||1<u)&&f.push({s:{r:k,c:n},e:{r:k+(t||1)-1,c:n+u-1}});var D={type:""};l=E(r,h,m+A,D);v={t:"s",v:l};var B="";if(""!==c(r).attr("data-tableexport-cellformat")){var x=parseInt(c(r).attr("data-tableexport-xlsxformatid")||0);0===x&&"function"===typeof a.mso.xslx.formatId.numbers&&
(x=a.mso.xslx.formatId.numbers(c(r),h,m+A));0===x&&"function"===typeof a.mso.xslx.formatId.date&&(x=a.mso.xslx.formatId.date(c(r),h,m+A));if(49===x||"@"===x)B="s";else if("number"===D.type||0<x&&14>x||36<x&&41>x||48===x)B="n";else if("date"===D.type||13<x&&37>x||44<x&&48>x||56===x)B="d"}else B="s";if(null!=l)if(0===l.length)v.t="z";else if(0!==l.trim().length&&"s"!==B)if("function"===D.type)v={f:l};else if("TRUE"===l)v={t:"b",v:!0};else if("FALSE"===l)v={t:"b",v:!1};else if(""===B&&c(r).find("a").length)l=
"href"!==a.htmlHyperlink?l:"",v={f:'=HYPERLINK("'+c(r).find("a").attr("href")+(l.length?'","'+l:"")+'")'};else if("n"===B||isFinite(Ca(l,a.numbers.output))){if(r=Ca(l,a.numbers.output),0===x&&"function"!==typeof a.mso.xslx.formatId.numbers&&(x=a.mso.xslx.formatId.numbers),isFinite(r)||isFinite(l))v={t:"n",v:isFinite(r)?r:l,z:"string"===typeof x?x:x in w?w[x]:"0.00"}}else if(!1!==(r=La(l))||"d"===B)0===x&&"function"!==typeof a.mso.xslx.formatId.date&&(x=a.mso.xslx.formatId.date),v={t:"d",v:!1!==r?
r:l,z:"string"===typeof x?x:x in w?w[x]:"m/d/yy"};d[na({c:n,r:k})]=v;g.e.c<n&&(g.e.c=n);n+=u}++k}f.length&&(d["!merges"]=f);q.length&&(d["!rows"]=q);g.e.r=k-1;d["!ref"]=oa(g);1E7<=k&&(d["!fullref"]=oa((g.e.r=e.length-h+k-1,g)));e="";"string"===typeof a.mso.worksheetName&&a.mso.worksheetName.length?e=a.mso.worksheetName+" "+(aa.length+1):"undefined"!==typeof a.mso.worksheetName[aa.length]&&(e=a.mso.worksheetName[aa.length]);e.length||(e=b.find("caption").text()||"");e.length||(e="Table "+(aa.length+
1));e=c.trim(e.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31));aa.push(e);XLSX.utils.book_append_sheet(Fa,d,e)});k=XLSX.write(Fa,{type:"binary",bookType:a.mso.fileFormat,bookSST:!1});M(Oa(k),a.fileName+"."+a.mso.fileFormat,"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","UTF-8","",!1)}else if("excel"===a.type||"xls"===a.type||"word"===a.type||"doc"===a.type){k="excel"===a.type||"xls"===a.type?"excel":"word";r="excel"===k?"xls":"doc";m='xmlns:x="urn:schemas-microsoft-com:office:'+
k+'"';var H="",ba="";c(C).filter(function(){return I(c(this))}).each(function(){var b=c(this);""===ba&&(ba=a.mso.worksheetName||b.find("caption").text()||"Table",ba=c.trim(ba.replace(/[\\\/[\]*:?'"]/g,"").substring(0,31)));!1===a.exportHiddenCells&&(J=b.find("tr, th, td").filter(":hidden"),V=0<J.length);n=0;G=[];T=S(this);H+="<table><thead>";u=y(b);c(u).each(function(){var b=c(this);t="";B(this,"th,td",n,u.length,function(c,d,f){if(null!==c){var e="";t+="<th";if(a.mso.styles.length){var g=document.defaultView.getComputedStyle(c,
null),h=document.defaultView.getComputedStyle(b[0],null),k;for(k in a.mso.styles){var m=g[a.mso.styles[k]];""===m&&(m=h[a.mso.styles[k]]);""!==m&&"0px none rgb(0, 0, 0)"!==m&&"rgba(0, 0, 0, 0)"!==m&&(e+=""===e?'style="':";",e+=a.mso.styles[k]+":"+m)}}""!==e&&(t+=" "+e+'"');e=O(c);0<e&&(t+=' colspan="'+e+'"');e=U(c);0<e&&(t+=' rowspan="'+e+'"');t+=">"+E(c,d,f)+"</th>"}});0<t.length&&(H+="<tr>"+t+"</tr>");n++});H+="</thead><tbody>";w=v(b);c(w).each(function(){var b=c(this);t="";B(this,"td,th",n,u.length+
w.length,function(d,g,f){if(null!==d){var e=E(d,g,f),q="",h=c(d).attr("data-tableexport-msonumberformat");"undefined"===typeof h&&"function"===typeof a.mso.onMsoNumberFormat&&(h=a.mso.onMsoNumberFormat(d,g,f));"undefined"!==typeof h&&""!==h&&(q="style=\"mso-number-format:'"+h+"'");if(a.mso.styles.length){g=document.defaultView.getComputedStyle(d,null);f=document.defaultView.getComputedStyle(b[0],null);for(var k in a.mso.styles)h=g[a.mso.styles[k]],""===h&&(h=f[a.mso.styles[k]]),""!==h&&"0px none rgb(0, 0, 0)"!==
h&&"rgba(0, 0, 0, 0)"!==h&&(q+=""===q?'style="':";",q+=a.mso.styles[k]+":"+h)}t+="<td";""!==q&&(t+=" "+q+'"');q=O(d);0<q&&(t+=' colspan="'+q+'"');d=U(d);0<d&&(t+=' rowspan="'+d+'"');"string"===typeof e&&""!==e&&(e=Aa(e),e=e.replace(/\n/g,"<br>"));t+=">"+e+"</td>"}});0<t.length&&(H+="<tr>"+t+"</tr>");n++});a.displayTableName&&(H+="<tr><td></td></tr><tr><td></td></tr><tr><td>"+E(c("<p>"+a.tableName+"</p>"))+"</td></tr>");H+="</tbody></table>"});m='<html xmlns:o="urn:schemas-microsoft-com:office:office" '+
m+' xmlns="http://www.w3.org/TR/REC-html40">'+('<meta http-equiv="content-type" content="application/vnd.ms-'+k+'; charset=UTF-8">');m+="<head>";"excel"===k&&(m+="\x3c!--[if gte mso 9]>",m+="<xml>",m+="<x:ExcelWorkbook>",m+="<x:ExcelWorksheets>",m+="<x:ExcelWorksheet>",m+="<x:Name>",m+=ba,m+="</x:Name>",m+="<x:WorksheetOptions>",m+="<x:DisplayGridlines/>",a.mso.rtl&&(m+="<x:DisplayRightToLeft/>"),m+="</x:WorksheetOptions>",m+="</x:ExcelWorksheet>",m+="</x:ExcelWorksheets>",m+="</x:ExcelWorkbook>",
m+="</xml>",m+="<![endif]--\x3e");m+="<style>";m+="@page { size:"+a.mso.pageOrientation+"; mso-page-orientation:"+a.mso.pageOrientation+"; }";m+="@page Section1 {size:"+N[a.mso.pageFormat][0]+"pt "+N[a.mso.pageFormat][1]+"pt";m+="; margin:1.0in 1.25in 1.0in 1.25in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";m+="div.Section1 {page:Section1;}";m+="@page Section2 {size:"+N[a.mso.pageFormat][1]+"pt "+N[a.mso.pageFormat][0]+"pt";m+=";mso-page-orientation:"+a.mso.pageOrientation+
";margin:1.25in 1.0in 1.25in 1.0in;mso-header-margin:.5in;mso-footer-margin:.5in;mso-paper-source:0;}";m+="div.Section2 {page:Section2;}";m+="br {mso-data-placement:same-cell;}";m+="</style>";m+="</head>";m+="<body>";m+='<div class="Section'+("landscape"===a.mso.pageOrientation?"2":"1")+'">';m+=H;m+="</div>";m+="</body>";m+="</html>";if("string"===a.outputMode)return m;if("base64"===a.outputMode)return K(m);M(m,a.fileName+"."+r,"application/vnd.ms-"+k,"","base64",!1)}else if("png"===a.type)html2canvas(c(C)[0]).then(function(b){b=
b.toDataURL();for(var c=atob(b.substring(22)),e=new ArrayBuffer(c.length),g=new Uint8Array(e),f=0;f<c.length;f++)g[f]=c.charCodeAt(f);if("string"===a.outputMode)return c;if("base64"===a.outputMode)return K(b);"window"===a.outputMode?window.open(b):M(e,a.fileName+".png","image/png","","",!1)});else if("pdf"===a.type)if(!0===a.pdfmake.enabled){k=[];var Ga=[];n=0;G=[];r=function(a,d,e){var b=0;c(a).each(function(){var a=[];B(this,d,n,e,function(b,c,d){if("undefined"!==typeof b&&null!==b){var e=O(b),
f=U(b);b=E(b,c,d)||" ";1<e||1<f?a.push({colSpan:e||1,rowSpan:f||1,text:b}):a.push(b)}else a.push(" ")});a.length&&Ga.push(a);b<a.length&&(b=a.length);n++});return b};u=y(c(this));m=r(u,"th,td",u.length);for(R=k.length;R<m;R++)k.push("*");w=v(c(this));r(w,"th,td",u.length+w.length);k={content:[{table:{headerRows:u.length,widths:k,body:Ga}}]};"undefined"!==typeof pdfMake&&(pdfMake.fonts={Roboto:{normal:"Roboto-Regular.ttf",bold:"Roboto-Medium.ttf",italics:"Roboto-Italic.ttf",bolditalics:"Roboto-MediumItalic.ttf"}},
pdfMake.vfs.hasOwnProperty("Mirza-Regular.ttf")?(a.pdfmake.docDefinition.defaultStyle.font="Mirza",c.extend(!0,pdfMake.fonts,{Mirza:{normal:"Mirza-Regular.ttf",bold:"Mirza-Bold.ttf",italics:"Mirza-Medium.ttf",bolditalics:"Mirza-SemiBold.ttf"}})):pdfMake.vfs.hasOwnProperty("gbsn00lp.ttf")?(a.pdfmake.docDefinition.defaultStyle.font="gbsn00lp",c.extend(!0,pdfMake.fonts,{gbsn00lp:{normal:"gbsn00lp.ttf",bold:"gbsn00lp.ttf",italics:"gbsn00lp.ttf",bolditalics:"gbsn00lp.ttf"}})):pdfMake.vfs.hasOwnProperty("ZCOOLXiaoWei-Regular.ttf")&&
(a.pdfmake.docDefinition.defaultStyle.font="ZCOOLXiaoWei",c.extend(!0,pdfMake.fonts,{ZCOOLXiaoWei:{normal:"ZCOOLXiaoWei-Regular.ttf",bold:"ZCOOLXiaoWei-Regular.ttf",italics:"ZCOOLXiaoWei-Regular.ttf",bolditalics:"ZCOOLXiaoWei-Regular.ttf"}})),c.extend(!0,k,a.pdfmake.docDefinition),c.extend(!0,pdfMake.fonts,a.pdfmake.fonts),"undefined"!==typeof pdfMake.createPdf&&pdfMake.createPdf(k).getBuffer(function(b){M(b,a.fileName+".pdf","application/pdf","","",!1)}))}else if(!1===a.jspdf.autotable){k={dim:{w:fa(c(C).first().get(0),
"width","mm"),h:fa(c(C).first().get(0),"height","mm")},pagesplit:!1};var Ha=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format);Ha.addHTML(c(C).first(),a.jspdf.margins.left,a.jspdf.margins.top,k,function(){ua(Ha,!1)})}else{var g=a.jspdf.autotable.tableExport;if("string"===typeof a.jspdf.format&&"bestfit"===a.jspdf.format.toLowerCase()){var ia="",ca="",Ia=0;c(C).each(function(){if(I(c(this))){var a=fa(c(this).get(0),"width","pt");if(a>Ia){a>N.a0[0]&&(ia="a0",ca="l");for(var d in N)N.hasOwnProperty(d)&&
N[d][1]>a&&(ia=d,ca="l",N[d][0]>a&&(ca="p"));Ia=a}}});a.jspdf.format=""===ia?"a4":ia;a.jspdf.orientation=""===ca?"w":ca}if(null==g.doc&&(g.doc=new jsPDF(a.jspdf.orientation,a.jspdf.unit,a.jspdf.format),g.wScaleFactor=1,g.hScaleFactor=1,"function"===typeof a.jspdf.onDocCreated))a.jspdf.onDocCreated(g.doc);!0===g.outputImages&&(g.images={});"undefined"!==typeof g.images&&(c(C).filter(function(){return I(c(this))}).each(function(){var b=0;G=[];!1===a.exportHiddenCells&&(J=c(this).find("tr, th, td").filter(":hidden"),
V=0<J.length);u=y(c(this));w=v(c(this));c(w).each(function(){B(this,"td,th",u.length+b,u.length+w.length,function(a){wa(a,c(a).children(),g)});b++})}),u=[],w=[]);Ka(g,function(){c(C).filter(function(){return I(c(this))}).each(function(){var b;n=0;G=[];!1===a.exportHiddenCells&&(J=c(this).find("tr, th, td").filter(":hidden"),V=0<J.length);T=S(this);g.columns=[];g.rows=[];g.teCells={};if("function"===typeof g.onTable&&!1===g.onTable(c(this),a))return!0;a.jspdf.autotable.tableExport=null;var d=c.extend(!0,
{},a.jspdf.autotable);a.jspdf.autotable.tableExport=g;d.margin={};c.extend(!0,d.margin,a.jspdf.margins);d.tableExport=g;"function"!==typeof d.beforePageContent&&(d.beforePageContent=function(a){if(1===a.pageCount){var b=a.table.rows.concat(a.table.headerRow);c.each(b,function(){0<this.height&&(this.height+=(2-1.15)/2*this.styles.fontSize,a.table.height+=(2-1.15)/2*this.styles.fontSize)})}});"function"!==typeof d.createdHeaderCell&&(d.createdHeaderCell=function(a,b){a.styles=c.extend({},b.row.styles);
if("undefined"!==typeof g.columns[b.column.dataKey]){var e=g.columns[b.column.dataKey];if("undefined"!==typeof e.rect){a.contentWidth=e.rect.width;if("undefined"===typeof g.heightRatio||0===g.heightRatio){var f=b.row.raw[b.column.dataKey].rowspan?b.row.raw[b.column.dataKey].rect.height/b.row.raw[b.column.dataKey].rowspan:b.row.raw[b.column.dataKey].rect.height;g.heightRatio=a.styles.rowHeight/f}f=b.row.raw[b.column.dataKey].rect.height*g.heightRatio;f>a.styles.rowHeight&&(a.styles.rowHeight=f)}a.styles.halign=
"inherit"===d.headerStyles.halign?"center":d.headerStyles.halign;a.styles.valign=d.headerStyles.valign;"undefined"!==typeof e.style&&!0!==e.style.hidden&&("inherit"===d.headerStyles.halign&&(a.styles.halign=e.style.align),"inherit"===d.styles.fillColor&&(a.styles.fillColor=e.style.bcolor),"inherit"===d.styles.textColor&&(a.styles.textColor=e.style.color),"inherit"===d.styles.fontStyle&&(a.styles.fontStyle=e.style.fstyle))}});"function"!==typeof d.createdCell&&(d.createdCell=function(a,b){b=g.teCells[b.row.index+
":"+b.column.dataKey];a.styles.halign="inherit"===d.styles.halign?"center":d.styles.halign;a.styles.valign=d.styles.valign;"undefined"!==typeof b&&"undefined"!==typeof b.style&&!0!==b.style.hidden&&("inherit"===d.styles.halign&&(a.styles.halign=b.style.align),"inherit"===d.styles.fillColor&&(a.styles.fillColor=b.style.bcolor),"inherit"===d.styles.textColor&&(a.styles.textColor=b.style.color),"inherit"===d.styles.fontStyle&&(a.styles.fontStyle=b.style.fstyle))});"function"!==typeof d.drawHeaderCell&&
(d.drawHeaderCell=function(a,b){var c=g.columns[b.column.dataKey];return(!0!==c.style.hasOwnProperty("hidden")||!0!==c.style.hidden)&&0<=c.rowIndex?va(a,b,c):!1});"function"!==typeof d.drawCell&&(d.drawCell=function(a,b){var d=g.teCells[b.row.index+":"+b.column.dataKey];if(!0!==("undefined"!==typeof d&&d.isCanvas))va(a,b,d)&&(g.doc.rect(a.x,a.y,a.width,a.height,a.styles.fillStyle),"undefined"===typeof d||"undefined"!==typeof d.hasUserDefText&&!0===d.hasUserDefText||"undefined"===typeof d.elements||
!d.elements.length?za(a,{},g):(b=a.height/d.rect.height,b>g.hScaleFactor&&(g.hScaleFactor=b),g.wScaleFactor=a.width/d.rect.width,b=a.textPos.y,ya(a,d.elements,g),a.textPos.y=b,za(a,d.elements,g)));else{d=d.elements[0];var e=c(d).attr("data-tableexport-canvas"),f=d.getBoundingClientRect();a.width=f.width*g.wScaleFactor;a.height=f.height*g.hScaleFactor;b.row.height=a.height;ta(a,d,e,g)}return!1});g.headerrows=[];u=y(c(this));c(u).each(function(){b=0;g.headerrows[n]=[];B(this,"th,td",n,u.length,function(a,
c,d){var e=Ba(a);e.title=E(a,c,d);e.key=b++;e.rowIndex=n;g.headerrows[n].push(e)});n++});if(0<n)for(var e=n-1;0<=e;)c.each(g.headerrows[e],function(){var a=this;0<e&&null===this.rect&&(a=g.headerrows[e-1][this.key]);null!==a&&0<=a.rowIndex&&(!0!==a.style.hasOwnProperty("hidden")||!0!==a.style.hidden)&&g.columns.push(a)}),e=0<g.columns.length?-1:e-1;var k=0;w=[];w=v(c(this));c(w).each(function(){var a=[];b=0;B(this,"td,th",n,u.length+w.length,function(d,e,f){if("undefined"===typeof g.columns[b]){var h=
{title:"",key:b,style:{hidden:!0}};g.columns.push(h)}a.push(E(d,e,f));"undefined"!==typeof d&&null!==d?(h=Ba(d),h.isCanvas=d.hasAttribute("data-tableexport-canvas"),h.elements=h.isCanvas?c(d):c(d).children(),"undefined"!==typeof c(d).data("teUserDefText")&&(h.hasUserDefText=!0)):(h=c.extend(!0,{},g.teCells[k+":"+(b-1)]),h.colspan=-1);g.teCells[k+":"+b++]=h});a.length&&(g.rows.push(a),k++);n++});if("function"===typeof g.onBeforeAutotable)g.onBeforeAutotable(c(this),g.columns,g.rows,d);g.doc.autoTable(g.columns,
g.rows,d);if("function"===typeof g.onAfterAutotable)g.onAfterAutotable(c(this),d);a.jspdf.autotable.startY=g.doc.autoTableEndPosY()+d.margin.top});ua(g.doc,"undefined"!==typeof g.images&&!1===jQuery.isEmptyObject(g.images));"undefined"!==typeof g.headerrows&&(g.headerrows.length=0);"undefined"!==typeof g.columns&&(g.columns.length=0);"undefined"!==typeof g.rows&&(g.rows.length=0);delete g.doc;g.doc=null})}if("function"===typeof a.onTableExportEnd)a.onTableExportEnd();return this}})(jQuery);

View File

@ -0,0 +1,93 @@
<?php
//
// ZoneMinder web stats view file, $Date$, $Revision$
// Copyright (C) 2001-2008 Philip Coombes
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canView( 'Events' ) )
{
$view = "error";
return;
}
if ( !isset($row) ) $row='';
$sql = 'SELECT S.*,E.*,Z.Name AS ZoneName,Z.Units,Z.Area,M.Name AS MonitorName FROM Stats AS S LEFT JOIN Events AS E ON S.EventId = E.Id LEFT JOIN Zones AS Z ON S.ZoneId = Z.Id LEFT JOIN Monitors AS M ON E.MonitorId = M.Id WHERE S.EventId = ? AND S.FrameId = ? ORDER BY S.ZoneId';
$stats = dbFetchAll( $sql, NULL, array( $eid, $fid ) );
?>
<table id="contentStatsTable<?php echo $row ?>"
data-toggle="table"
data-toolbar="#toolbar"
class="table-sm table-borderless contentStatsTable"
cellspacing="0">
<caption><?php echo translate('Stats') ?> - <?php echo $eid ?> - <?php echo $fid ?></caption>
<thead>
<tr>
<th class="colZone font-weight-bold" data-align="center"><?php echo translate('Zone') ?></th>
<th class="colPixelDiff font-weight-bold" data-align="center"><?php echo translate('PixelDiff') ?></th>
<th class="colAlarmPx font-weight-bold" data-align="center"><?php echo translate('AlarmPx') ?></th>
<th class="colFilterPx font-weight-bold" data-align="center"><?php echo translate('FilterPx') ?></th>
<th class="colBlobPx font-weight-bold" data-align="center"><?php echo translate('BlobPx') ?></th>
<th class="colBlobs font-weight-bold" data-align="center"><?php echo translate('Blobs') ?></th>
<th class="colBlobSizes font-weight-bold" data-align="center"><?php echo translate('BlobSizes') ?></th>
<th class="colAlarmLimits font-weight-bold" data-align="center"><?php echo translate('AlarmLimits') ?></th>
<th class="colScore font-weight-bold" data-align="center"><?php echo translate('Score') ?></th>
</tr>
</thead>
<tbody>
<?php
if ( count($stats) )
{
foreach ( $stats as $stat )
{
?>
<tr>
<td class="colZone"><?php echo validHtmlStr($stat['ZoneName']) ?></td>
<td class="colPixelDiff"><?php echo validHtmlStr($stat['PixelDiff']) ?></td>
<td class="colAlarmPx"><?php echo sprintf( "%d (%d%%)", $stat['AlarmPixels'], (100*$stat['AlarmPixels']/$stat['Area']) ) ?></td>
<td class="colFilterPx"><?php echo sprintf( "%d (%d%%)", $stat['FilterPixels'], (100*$stat['FilterPixels']/$stat['Area']) ) ?></td>
<td class="colBlobPx"><?php echo sprintf( "%d (%d%%)", $stat['BlobPixels'], (100*$stat['BlobPixels']/$stat['Area']) ) ?></td>
<td class="colBlobs"><?php echo validHtmlStr($stat['Blobs']) ?></td>
<?php
if ( $stat['Blobs'] > 1 ) {
?>
<td class="colBlobSizes"><?php echo sprintf( "%d-%d (%d%%-%d%%)", $stat['MinBlobSize'], $stat['MaxBlobSize'], (100*$stat['MinBlobSize']/$stat['Area']), (100*$stat['MaxBlobSize']/$stat['Area']) ) ?></td>
<?php
} else {
?>
<td class="colBlobSizes"><?php echo sprintf( "%d (%d%%)", $stat['MinBlobSize'], 100*$stat['MinBlobSize']/$stat['Area'] ) ?></td>
<?php
}
?>
<td class="colAlarmLimits"><?php echo validHtmlStr($stat['MinX'].",".$stat['MinY']."-".$stat['MaxX'].",".$stat['MaxY']) ?></td>
<td class="colScore"><?php echo $stat['Score'] ?></td>
</tr>
<?php
}
} else {
?>
<tr>
<td class="rowNoStats" colspan="9"><?php echo translate('NoStatisticsRecorded') ?></td>
</tr>
<?php
}
?>
</tbody>
</table>

View File

@ -283,10 +283,27 @@ for( $monitor_i = 0; $monitor_i < count($displayMonitors); $monitor_i += 1 ) {
<td class="colId"><a <?php echo ($stream_available ? 'href="?view=watch&amp;mid='.$monitor['Id'].'">' : '>') . $monitor['Id'] ?></a></td>
<?php
}
$imgHTML='';
if ( ZM_WEB_LIST_THUMBS && $monitor['Status'] == 'Connected' && $running ) {
$options = array();
$options['width'] = ZM_WEB_LIST_THUMB_WIDTH;
$options['height'] = ZM_WEB_LIST_THUMB_HEIGHT;
$options['mode'] = 'single';
$stillSrc = $Monitor->getStreamSrc($options);
$streamSrc = $Monitor->getStreamSrc(array('scale'=>$scale));
$thmbWidth = ( $options['width'] ) ? 'width:'.$options['width'].'px;' : '';
$thmbHeight = ( $options['height'] ) ? 'width:'.$options['height'].'px;' : '';
$imgHTML = '<div class="colThumbnail zoom-right"><img id="thumbnail' .$Monitor->Id(). '" src="' .$stillSrc. '" style='
.$thmbWidth.$thmbHeight. '" stream_src="' .$streamSrc. '" still_src="' .$stillSrc. '"/></div>';
}
?>
<td class="colName">
<i class="material-icons md-18 <?php echo $dot_class ?>">lens</i>
<a <?php echo ($stream_available ? 'href="?view=watch&amp;mid='.$monitor['Id'].'">' : '>') . validHtmlStr($monitor['Name']) ?></a><br/>
<?php echo $imgHTML ?>
<div class="small text-nowrap text-muted">
<?php echo implode('<br/>',

View File

@ -104,12 +104,11 @@ xhtmlHeaders(__FILE__, translate('Events'));
?>
<body>
<div id="page">
<?php echo getNavBarHTML() ?>
<?php echo getNavBarHTML() ?>
<div id="page" class="container-fluid p-3">
<!-- Toolbar button placement and styling handled by bootstrap-tables -->
<div id="toolbar">
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" ><i class="fa fa-arrow-left"></i></button>
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
<button id="tlineBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('ShowTimeline') ?>" ><i class="fa fa-history"></i></button>
<button id="viewBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('View') ?>" disabled><i class="fa fa-binoculars"></i></button>
@ -120,8 +119,9 @@ xhtmlHeaders(__FILE__, translate('Events'));
<button id="downloadBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('DownloadVideo') ?>" disabled><i class="fa fa-download"></i></button>
<button id="deleteBtn" class="btn btn-danger" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Delete') ?>" disabled><i class="fa fa-trash"></i></button>
</div>
<!-- Table styling handled by bootstrap-tables. Initially hidden until rendering done -->
<div class="table-responsive-sm p-3">
<!-- Table styling handled by bootstrap-tables -->
<div class="row justify-content-center">
<table
id="eventTable"
data-toggle="table"
@ -135,6 +135,7 @@ xhtmlHeaders(__FILE__, translate('Events'));
data-click-to-select="true"
data-remember-order="true"
data-show-columns="true"
data-show-export="true"
data-uncheckAll="true"
data-toolbar="#toolbar"
data-show-fullscreen="true"
@ -213,7 +214,6 @@ if ( $results ) {
<td class="text-center"><?php echo ( $event->Archived() ) ? 'Yes' : 'No' ?></td>
<td class="text-center"><?php echo ( $event->Emailed() ) ? 'Yes' : 'No' ?></td>
<td><?php echo makePopupLink( '?view=monitor&amp;mid='.$event->MonitorId(), 'zmMonitor'.$event->MonitorId(), 'monitor', $event->MonitorName(), canEdit( 'Monitors' ) ) ?></td>
<td><?php echo makePopupLink( '?view=eventdetail&amp;eid='.$event->Id(), 'zmEventDetail', 'eventdetail', validHtmlStr($event->Cause()), canEdit( 'Events' ), 'title="'.htmlspecialchars($event->Notes()).'"' ) ?>
<?php
# display notes as small text
@ -233,13 +233,9 @@ if ( $results ) {
<td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->StartTime())) ?></td>
<td><?php echo strftime(STRF_FMT_DATETIME_SHORTER, strtotime($event->EndTime())) ?></td>
<td><?php echo gmdate('H:i:s', $event->Length()) ?></td>
<td><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'),
$event->Frames() ) ?></td>
<td><?php echo makePopupLink( '?view=frames&amp;eid='.$event->Id(), 'zmFrames',
( ZM_WEB_LIST_THUMBS ? array('frames', ZM_WEB_LIST_THUMB_WIDTH, ZM_WEB_LIST_THUMB_HEIGHT) : 'frames'),
$event->AlarmFrames() ) ?></td>
<td><?php echo gmdate('H:i:s', $event->Length() ) ?></td>
<td><a href="?view=frames&amp;eid=<?php echo $event->Id() ?>"><?php echo $event->Frames() ?></a></td>
<td><a href="?view=frames&amp;eid=<?php echo $event->Id() ?>"><?php echo $event->AlarmFrames() ?></a></td>
<td><?php echo $event->TotScore() ?></td>
<td><?php echo $event->AvgScore() ?></td>
<td><?php echo makePopupLink(

View File

@ -85,22 +85,26 @@ $focusWindow = true;
xhtmlHeaders(__FILE__, translate('Frame').' - '.$Event->Id().' - '.$Frame->FrameId());
?>
<body>
<div id="page">
<div id="header">
<form>
<div id="headerButtons">
<?php if ( ZM_RECORD_EVENT_STATS && $alarmFrame ) { echo makePopupLink( '?view=stats&amp;eid='.$Event->Id().'&amp;fid='.$Frame->FrameId(), 'zmStats', 'stats', translate('Stats') ); } ?>
<?php if ( canEdit('Events') ) { ?><a href="?view=none&amp;action=delete&amp;markEid=<?php echo $Event->Id() ?>"><?php echo translate('Delete') ?></a><?php } ?>
<a href="#" data-on-click="closeWindow"><?php echo translate('Close') ?></a>
<?php echo getNavBarHTML() ?>
<div id="page p-0">
<div class="d-flex flex-row justify-content-between px-3 pt-1">
<div id="toolbar" >
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
<button id="statsBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Stats') ?>" ><i class="fa fa-info"></i></button>
</div>
<div id="scaleControl"><label for="scale"><?php echo translate('Scale') ?></label><?php echo htmlSelect('scale', $scales, $scale); ?></div>
<h2><?php echo translate('Frame') ?> <?php echo $Event->Id().'-'.$Frame->FrameId().' ('.$Frame->Score().')' ?></h2>
<input type="hidden" name="base_width" id="base_width" value="<?php echo $Event->Width(); ?>"/>
<input type="hidden" name="base_height" id="base_height" value="<?php echo $Event->Height(); ?>"/>
</form>
<form>
<div id="scaleControl"><label for="scale"><?php echo translate('Scale') ?></label><?php echo htmlSelect('scale', $scales, $scale); ?></div>
<input type="hidden" name="base_width" id="base_width" value="<?php echo $Event->Width(); ?>"/>
<input type="hidden" name="base_height" id="base_height" value="<?php echo $Event->Height(); ?>"/>
</form>
</div>
<div id="content">
<p id="image">
<div id="content">
<p id="image">
<?php if ( $imageData['hasAnalImage'] ) {
echo sprintf('<a href="?view=frame&amp;eid=%d&amp;fid=%d&scale=%d&amp;show=%s">', $Event->Id(), $Frame->FrameId(), $scale, ( $show=='anal'?'capt':'anal' ) );
} ?>

View File

@ -111,108 +111,82 @@ $focusWindow = true;
xhtmlHeaders(__FILE__, translate('Frames').' - '.$Event->Id());
?>
<body>
<div id="page">
<div id="header">
<div id="headerButtons"><a href="#" data-on-click="closeWindow"><?php echo translate('Close') ?></a></div>
<h2><?php echo translate('Frames') ?> - <?php echo $Event->Id() ?></h2>
<div id="pagination">
<?php
if ( $pagination ) {
?>
<h2 class="pagination"><?php echo $pagination ?></h2>
<?php
}
?>
<?php
if ( $pages > 1 ) {
if ( !empty($page) ) {
?>
<a href="?view=<?php echo $view ?>&amp;page=0<?php echo $totalQuery ?>"><?php echo translate('ViewAll') ?></a>
<?php
} else {
?>
<a href="?view=<?php echo $view ?>&amp;page=1<?php echo $totalQuery ?>"><?php echo translate('ViewPaged') ?></a>
<?php
}
}
?>
</div>
<?php echo getNavBarHTML() ?>
<div id="page" class="container-fluid p-3">
<!-- Toolbar button placement and styling handled by bootstrap-tables -->
<div id="toolbar">
<button type="button" id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button type="button" id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
</div>
<div id="content">
<form name="contentForm" id="contentForm" method="get" action="?">
<input type="hidden" name="view" value="none"/>
<input type="hidden" name="view" value="<?php echo $view ?>"/>
<input type="hidden" name="action" value=""/>
<input type="hidden" name="page" value="<?php echo $page ?>"/>
<input type="hidden" name="eid" value="<?php echo $eid ?>"/>
<?php echo $filter->hidden_fields() ?>
<input type="hidden" name="sort_field" value="<?php echo validHtmlStr($_REQUEST['sort_field']) ?>"/>
<input type="hidden" name="sort_asc" value="<?php echo validHtmlStr($_REQUEST['sort_asc']) ?>"/>
<input type="hidden" name="limit" value="<?php echo $limit ?>"/>
<table id="contentTable" class="major">
<thead>
<tr>
<th class="colId"><a href="<?php echo sortHeader('FramesFrameId') ?>"><?php echo translate('Frame Id') ?><?php echo sortTag('FramesFrameId') ?></a></th>
<th class="colType"><a href="<?php echo sortHeader('FramesType') ?>"><?php echo translate('Type') ?><?php echo sortTag('FramesType') ?></a></th>
<th class="colTimeStamp"><a href="<?php echo sortHeader('FramesTimeStamp') ?>"><?php echo translate('TimeStamp') ?><?php echo sortTag('FramesTimeStamp') ?></a></th>
<th class="colTimeDelta"><a href="<?php echo sortHeader('FramesDelta') ?>"><?php echo translate('TimeDelta') ?><?php echo sortTag('FramesDelta') ?></a></th>
<th class="colScore"><a href="<?php echo sortHeader('FramesScore') ?>"><?php echo translate('Score') ?><?php echo sortTag('FramesScore') ?></a></th>
<!-- Table styling handled by bootstrap-tables -->
<div class="row justify-content-center">
<table
id="framesTable"
data-toggle="table"
data-pagination="true"
data-show-pagination-switch="true"
data-page-list="[10, 25, 50, 100, 200, All]"
data-search="true"
data-cookie="true"
data-cookie-id-table="zmFramesTable"
data-cookie-expire="2y"
data-remember-order="true"
data-show-columns="true"
data-show-export="true"
data-toolbar="#toolbar"
data-show-fullscreen="true"
data-maintain-meta-data="true"
data-mobile-responsive="true"
data-buttons-class="btn btn-normal"
data-detail-view="true"
data-detail-formatter="detailFormatter"
data-show-toggle="true"
class="table-sm table-borderless">
<thead>
<!-- Row styling is handled by bootstrap-tables -->
<tr>
<th class="px-3" data-align="center" data-sortable="false" data-field="EventId"><?php echo translate('EventId') ?></th>
<th class="px-3" data-align="center" data-sortable="true" data-field="FramesId"><?php echo translate('FrameId') ?></th>
<th class="px-3" data-align="center" data-sortable="true" data-field="FramesType"><?php echo translate('Type') ?></th>
<th class="px-3" data-align="center" data-sortable="true" data-field="FramesTimeStamp"><?php echo translate('TimeStamp') ?></th>
<th class="px-3" data-align="center" data-sortable="true" data-field="FramesDelta"><?php echo translate('TimeDelta') ?></th>
<th class="px-3" data-align="center" data-sortable="true" data-field="FramesScore"><?php echo translate('Score') ?></th>
>>>>>>> master
<?php
if ( ZM_WEB_LIST_THUMBS ) {
?>
<th class="colThumbnail"><?php echo translate('Thumbnail') ?></th>
<th class="px-3" data-align="center" data-sortable="false" data-field="Thumbnail"><?php echo translate('Thumbnail') ?></th>
<?php
}
?>
</tr>
</thead>
<tbody>
</tr>
</thead>
<tbody>
<?php
if ( count($frames) ) {
foreach ( $frames as $frame ) {
$Frame = new ZM\Frame($frame);
$class = strtolower($frame['Type']);
?>
<tr class="<?php echo $class ?>">
<td class="colId"><?php echo makePopupLink(
'?view=frame&amp;eid='.$Event->Id().'&amp;fid='.$frame['FrameId'], 'zmImage',
array(
'frame',
($scale ? $Event->Width()*$scale/100 : $Event->Width()),
($scale ? $Event->Height()*$scale/100 : $Event->Height())
),
$frame['FrameId'])
?></td>
<td class="colType"><?php echo $frame['Type'] ?></td>
<td class="colTimeStamp"><?php echo strftime(STRF_FMT_TIME, $frame['UnixTimeStamp']) ?></td>
<td class="colTimeDelta"><?php echo number_format($frame['Delta'], 2) ?></td>
<tr class="<?php echo strtolower($frame['Type']) ?>">
<td><?php echo $frame['EventId'] ?></td>
<td><?php echo $frame['FrameId'] ?></td>
<td><?php echo $frame['Type'] ?></td>
<td><?php echo strftime(STRF_FMT_TIME, $frame['UnixTimeStamp']) ?></td>
<td><?php echo number_format( $frame['Delta'], 2 ) ?></td>
<td><?php echo $frame['Score'] ?></td>
<?php
if ( ZM_RECORD_EVENT_STATS && ($frame['Type'] == 'Alarm') ) {
?>
<td class="colScore"><?php echo makePopupLink('?view=stats&amp;eid='.$Event->Id().'&amp;fid='.$frame['FrameId'], 'zmStats', 'stats', $frame['Score']) ?></td>
<?php
} else {
?>
<td class="colScore"><?php echo $frame['Score'] ?></td>
<?php
}
if ( ZM_WEB_LIST_THUMBS ) {
?>
<td class="colThumbnail">
<?php echo makePopupLink(
'?view=frame&amp;eid='.$Event->Id().'&amp;fid='.$frame['FrameId'],
'zmImage',
array('image', $Event->Width(), $Event->Height()),
'<img src="?view=image&amp;fid='.$Frame->Id().'&amp;'.
(ZM_WEB_LIST_THUMB_WIDTH?'width='.ZM_WEB_LIST_THUMB_WIDTH.'&amp;':'').
(ZM_WEB_LIST_THUMB_HEIGHT?'height='.ZM_WEB_LIST_THUMB_HEIGHT.'&amp;':'').
'filename='.$Event->MonitorId().'_'.$frame['EventId'].'_'.$frame['FrameId'].'.jpg" '.
(ZM_WEB_LIST_THUMB_WIDTH?'width="'.ZM_WEB_LIST_THUMB_WIDTH.'" ':'').
(ZM_WEB_LIST_THUMB_HEIGHT?'height="'.ZM_WEB_LIST_THUMB_HEIGHT.'" ':'').
' alt="'.$frame['FrameId'].'"/>'
) ?></td>
<?php
$base_img_src = '?view=image&amp;fid=' .$Frame->Id();
$thmb_width = ZM_WEB_LIST_THUMB_WIDTH ? 'width='.ZM_WEB_LIST_THUMB_WIDTH : '';
$thmb_height = ZM_WEB_LIST_THUMB_HEIGHT ? 'height='.ZM_WEB_LIST_THUMB_HEIGHT : '';
$thmb_fn = 'filename=' .$Event->MonitorId(). '_' .$frame['EventId']. '_' .$frame['FrameId']. '.jpg';
$img_src = join('&amp;', array_filter(array($base_img_src, $thmb_width, $thmb_height, $thmb_fn)));
$full_img_src = join('&amp;', array_filter(array($base_img_src, $thmb_fn)));
$frame_src = '?view=frame&amp;eid=' .$Event->Id(). '&amp;fid=' .$frame['FrameId'];
echo '<td class="colThumbnail zoom"><img src="' .$img_src. '" '.$thmb_width. ' ' .$thmb_height. 'img_src="' .$img_src. '" full_img_src="' .$full_img_src. '"></td>'.PHP_EOL;
}
?>
</tr>
@ -228,18 +202,18 @@ if ( count($frames) ) {
?>
</tbody>
</table>
<?php
if ( $pagination ) {
?>
<h3 class="pagination"><?php echo $pagination ?></h3>
</div>
</div>
<!-- Load the statistics for each frame -->
<!-- This content gets hidden on init and only revailed on detail view -->
<?php
$row = 0;
if ( count($frames) ) foreach ( $frames as $frame ) {
$eid = $frame['EventId'];
$fid = $frame['FrameId'];
include('_stats_table.php');
$row++;
}
?>
<div id="contentButtons">
</div>
</form>
</div>
</div>
</body>
</body>
</html>

View File

@ -1,3 +1,21 @@
function thumbnail_onmouseover(event) {
var img = event.target;
img.src = '';
img.src = img.getAttribute('stream_src');
}
function thumbnail_onmouseout(event) {
var img = event.target;
img.src = '';
img.src = img.getAttribute('still_src');
}
function initThumbAnimation() {
$j('.colThumbnail img').each(function() {
this.addEventListener('mouseover', thumbnail_onmouseover, false);
this.addEventListener('mouseout', thumbnail_onmouseout, false);
});
}
function setButtonStates( element ) {
var form = element.form;
@ -133,6 +151,9 @@ function initPage() {
axis: 'Y'} );
$j( "#consoleTableBody" ).disableSelection();
} );
// Setup the thumbnail video animation
initThumbAnimation();
}
function applySort(event, ui) {

View File

@ -36,6 +36,7 @@ function getArchivedSelections() {
}
function initPage() {
var backBtn = $j('#backBtn');
var viewBtn = $j('#viewBtn');
var archiveBtn = $j('#archiveBtn');
var unarchiveBtn = $j('#unarchiveBtn');
@ -49,6 +50,7 @@ function initPage() {
var icons = {
paginationSwitchDown: 'fa-caret-square-o-down',
paginationSwitchUp: 'fa-caret-square-o-up',
export: 'fa-download',
refresh: 'fa-sync',
toggleOff: 'fa-toggle-off',
toggleOn: 'fa-toggle-on',
@ -81,6 +83,10 @@ function initPage() {
downloadBtn.prop('disabled', !(selections.length && canViewEvents));
deleteBtn.prop('disabled', !(selections.length && canEditEvents));
});
// Don't enable the back button if there is no previous zm page to go back to
backBtn.prop('disabled', !document.referrer.length);
// Setup the thumbnail video animation
initThumbAnimation();
@ -90,18 +96,21 @@ function initPage() {
// Manage the BACK button
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
if ( document.referrer.length ) window.history.back();
window.history.back();
});
// Manage the REFRESH Button
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
// Manage the TIMELINE Button
document.getElementById("tlineBtn").addEventListener("click", function onTlineClick(evt) {
evt.preventDefault();
window.location.assign('?view=timeline'+filterQuery);
});
// Manage the VIEW button
document.getElementById("viewBtn").addEventListener("click", function onViewClick(evt) {
var selections = getIdSelections();
@ -110,6 +119,7 @@ function initPage() {
var filter = '&filter[Query][terms][0][attr]=Id&filter[Query][terms][0][op]=%3D%5B%5D&filter[Query][terms][0][val]='+selections.join('%2C');
window.location.href = thisUrl+'?view=event&eid='+selections[0]+filter+sortQuery+'&page=1&play=1';
});
// Manage the ARCHIVE button
document.getElementById("archiveBtn").addEventListener("click", function onArchiveClick(evt) {
var selections = getIdSelections();
@ -118,6 +128,7 @@ function initPage() {
$j.getJSON(thisUrl + '?view=events&action=archive&eids[]='+selections.join('&eids[]='));
window.location.reload(true);
});
// Manage the UNARCHIVE button
document.getElementById("unarchiveBtn").addEventListener("click", function onUnarchiveClick(evt) {
if ( ! canEditEvents ) {
@ -139,6 +150,7 @@ function initPage() {
window.location.reload(true);
}
});
// Manage the EDIT button
document.getElementById("editBtn").addEventListener("click", function onEditClick(evt) {
if ( ! canEditEvents ) {
@ -151,6 +163,7 @@ function initPage() {
evt.preventDefault();
createPopup('?view=eventdetail&eids[]='+selections.join('&eids[]='), 'zmEventDetail', 'eventdetail');
});
// Manage the EXPORT button
document.getElementById("exportBtn").addEventListener("click", function onExportClick(evt) {
var selections = getIdSelections();
@ -158,6 +171,7 @@ function initPage() {
evt.preventDefault();
window.location.assign('?view=export&eids[]='+selections.join('&eids[]='));
});
// Manage the DOWNLOAD VIDEO button
document.getElementById("downloadBtn").addEventListener("click", function onDownloadClick(evt) {
var selections = getIdSelections();
@ -165,6 +179,7 @@ function initPage() {
evt.preventDefault();
createPopup('?view=download&eids[]='+selections.join('&eids[]='), 'zmDownload', 'download');
});
// Manage the DELETE button
document.getElementById("deleteBtn").addEventListener("click", function onDeleteClick(evt) {
if ( ! canEditEvents ) {

View File

@ -39,3 +39,34 @@ if ( !scale ) {
document.addEventListener('DOMContentLoaded', function onDCL() {
document.getElementById('scale').addEventListener('change', changeScale);
});
function initPage() {
var backBtn = $j('#backBtn');
if ( scale == '0' || scale == 'auto' ) changeScale();
// Don't enable the back button if there is no previous zm page to go back to
backBtn.prop('disabled', !document.referrer.length);
// Manage the BACK button
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
window.history.back();
});
// Manage the REFRESH Button
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
// Manage the STATS button
document.getElementById("statsBtn").addEventListener("click", function onViewClick(evt) {
evt.preventDefault();
window.location.href = thisUrl+'?view=stats&eid='+eid+'&fid='+fid;
});
}
$j(document).ready(function() {
initPage();
});

View File

@ -1,3 +1,15 @@
<?php
global $scale;
global $eid;
global $fid;
global $alarmFrame;
?>
var scale = '<?php echo validJsStr($scale); ?>';
var SCALE_BASE = <?php echo SCALE_BASE ?>;
var eid = <?php echo $eid ?>;
var fid = <?php echo $fid ?>;
var record_event_stats = <?php echo ZM_RECORD_EVENT_STATS ?>;
var alarmFrame = <?php echo $alarmFrame ?>;

View File

@ -0,0 +1,91 @@
function thumbnail_onmouseover(event) {
var img = event.target;
img.src = '';
img.src = img.getAttribute('full_img_src');
}
function thumbnail_onmouseout(event) {
var img = event.target;
img.src = '';
img.src = img.getAttribute('img_src');
}
function initThumbAnimation() {
$j('.colThumbnail img').each(function() {
this.addEventListener('mouseover', thumbnail_onmouseover, false);
this.addEventListener('mouseout', thumbnail_onmouseout, false);
});
}
function processClicks(event, field, value, row, $element) {
if ( field == 'FramesScore' ) {
if ( value > 0 ) {
window.location.assign('?view=stats&eid='+row.EventId+'&fid='+row.FramesId);
} else {
alert("No statistics available");
}
} else {
window.location.assign('?view=frame&eid='+row.EventId+'&fid='+row.FramesId);
}
}
function detailFormatter(index, row, element) {
return $j(element).html($j('#contentStatsTable'+index).clone(true).show());
}
function initPage() {
var backBtn = $j('#backBtn');
var table = $j('#framesTable');
// Define the icons used in the bootstrap-table top-right toolbar
var icons = {
paginationSwitchDown: 'fa-caret-square-o-down',
paginationSwitchUp: 'fa-caret-square-o-up',
export: 'fa-download',
refresh: 'fa-sync',
toggleOff: 'fa-toggle-off',
toggleOn: 'fa-toggle-on',
columns: 'fa-th-list',
fullscreen: 'fa-arrows-alt',
detailOpen: 'fa-plus',
detailClose: 'fa-minus'
};
// Init the bootstrap-table
table.bootstrapTable('destroy').bootstrapTable({icons: icons});
// Hide these columns on first run when no cookie is saved
if ( !getCookie("zmFramesTable.bs.table.columns") ) {
table.bootstrapTable('hideColumn', 'FrameId');
}
// Hide the stats tables on init
$j(".contentStatsTable").hide();
// Disable the back button if there is nothing to go back to
backBtn.prop('disabled', !document.referrer.length);
// Setup the thumbnail animation
initThumbAnimation();
// Some toolbar events break the thumbnail animation, so re-init eventlistener
table.on('all.bs.table', initThumbAnimation);
// Load the associated frame image when the user clicks on a row
table.on('click-cell.bs.table', processClicks);
// Manage the BACK button
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
window.history.back();
});
// Manage the REFRESH Button
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
}
$j(document).ready(function() {
initPage();
});

View File

@ -0,0 +1,21 @@
function initPage() {
var backBtn = $j('#backBtn');
// Disable the back button if there is nothing to go back to
backBtn.prop('disabled', !document.referrer.length);
// Manage the BACK button
document.getElementById("backBtn").addEventListener("click", function onBackClick(evt) {
evt.preventDefault();
window.history.back();
});
// Manage the REFRESH Button
document.getElementById("refreshBtn").addEventListener("click", function onRefreshClick(evt) {
evt.preventDefault();
window.location.reload(true);
});
}
$j(document).ready(function() {
initPage();
});

View File

@ -249,14 +249,12 @@ function limitArea(field) {
limitRange(field, minValue, maxValue);
}
function highlightOn(point) {
var index = point.getAttribute('data-index');
function highlightOn(index) {
$('row'+index).addClass('highlight');
$('point'+index).addClass('highlight');
}
function highlightOff(point) {
var index = point.getAttribute('data-index');
function highlightOff(index) {
$('row'+index).removeClass('highlight');
$('point'+index).removeClass('highlight');
}
@ -328,17 +326,15 @@ function addPoint(index) {
if ( index >= (zone['Points'].length-1) ) {
nextIndex = 0;
}
var newX = parseInt(Math.round((zone['Points'][index]['x']+zone['Points'][nextIndex]['x'])/2));
var newY = parseInt(Math.round((zone['Points'][index]['y']+zone['Points'][nextIndex]['y'])/2));
if ( nextIndex == 0 ) {
zone['Points'][zone['Points'].length] = {'x': newX, 'y': newY};
} else {
zone['Points'].splice( nextIndex, 0, {'x': newX, 'y': newY} );
zone['Points'].splice(nextIndex, 0, {'x': newX, 'y': newY});
}
drawZonePoints();
// drawZonePoints calls updateZoneImage
//updateZoneImage();
//setActivePoint( nextIndex );
}
function delPoint(index) {
@ -421,10 +417,9 @@ function drawZonePoints() {
'top': zone['Points'][i].y
}
});
//div.addEvent('mouseover', highlightOn.pass(i));
div.onmouseover = window['highlightOn'].bind(div, div);
div.onmouseout = window['highlightOff'].bind(div, div);
div.addEvent('mouseover', highlightOn.pass(i));
div.addEvent('mouseout', highlightOff.pass(i));
div.inject($('imageFrame'));
div.makeDraggable( {
'container': $('imageFrame'),
@ -493,7 +488,7 @@ function drawZonePoints() {
cell.inject(row);
row.inject(tables[i%tables.length].getElement('tbody'));
}
} // end foreach point
// Sets up the SVG polygon
updateZoneImage();
}

View File

@ -27,83 +27,24 @@ if ( !canView( 'Events' ) )
$eid = validInt($_REQUEST['eid']);
$fid = validInt($_REQUEST['fid']);
$sql = 'SELECT S.*,E.*,Z.Name AS ZoneName,Z.Units,Z.Area,M.Name AS MonitorName FROM Stats AS S LEFT JOIN Events AS E ON S.EventId = E.Id LEFT JOIN Zones AS Z ON S.ZoneId = Z.Id LEFT JOIN Monitors AS M ON E.MonitorId = M.Id WHERE S.EventId = ? AND S.FrameId = ? ORDER BY S.ZoneId';
$stats = dbFetchAll( $sql, NULL, array( $eid, $fid ) );
$focusWindow = true;
xhtmlHeaders(__FILE__, translate('Stats')." - ".$eid." - ".$fid );
?>
<body>
<?php echo getNavBarHTML() ?>
<div id="page">
<div id="header">
<div id="headerButtons">
<a href="#" onclick="closeWindow(); return( false );"><?php echo translate('Close') ?></a>
</div>
<h2><?php echo translate('Stats') ?> - <?php echo $eid ?> - <?php echo $fid ?></h2>
<!-- Toolbar button placement and styling handled by bootstrap-tables -->
<div id="toolbar">
<button id="backBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Back') ?>" disabled><i class="fa fa-arrow-left"></i></button>
<button id="refreshBtn" class="btn btn-normal" data-toggle="tooltip" data-placement="top" title="<?php echo translate('Refresh') ?>" ><i class="fa fa-refresh"></i></button>
</div>
<div id="content">
<div id="content" class="row justify-content-center">
<form name="contentForm" id="contentForm" method="get" action="?">
<input type="hidden" name="view" value="none"/>
<table id="contentTable" class="major" cellspacing="0">
<thead>
<tr>
<th class="colZone"><?php echo translate('Zone') ?></th>
<th class="colPixelDiff"><?php echo translate('PixelDiff') ?></th>
<th class="colAlarmPx"><?php echo translate('AlarmPx') ?></th>
<th class="colFilterPx"><?php echo translate('FilterPx') ?></th>
<th class="colBlobPx"><?php echo translate('BlobPx') ?></th>
<th class="colBlobs"><?php echo translate('Blobs') ?></th>
<th class="colBlobSizes"><?php echo translate('BlobSizes') ?></th>
<th class="colAlarmLimits"><?php echo translate('AlarmLimits') ?></th>
<th class="colScore"><?php echo translate('Score') ?></th>
</tr>
</thead>
<tbody>
<?php
if ( count($stats) )
{
foreach ( $stats as $stat )
{
?>
<tr>
<td class="colZone"><?php echo validHtmlStr($stat['ZoneName']) ?></td>
<td class="colPixelDiff"><?php echo validHtmlStr($stat['PixelDiff']) ?></td>
<td class="colAlarmPx"><?php echo sprintf( "%d (%d%%)", $stat['AlarmPixels'], (100*$stat['AlarmPixels']/$stat['Area']) ) ?></td>
<td class="colFilterPx"><?php echo sprintf( "%d (%d%%)", $stat['FilterPixels'], (100*$stat['FilterPixels']/$stat['Area']) ) ?></td>
<td class="colBlobPx"><?php echo sprintf( "%d (%d%%)", $stat['BlobPixels'], (100*$stat['BlobPixels']/$stat['Area']) ) ?></td>
<td class="colBlobs"><?php echo validHtmlStr($stat['Blobs']) ?></td>
<?php
if ( $stat['Blobs'] > 1 )
{
?>
<td class="colBlobSizes"><?php echo sprintf( "%d-%d (%d%%-%d%%)", $stat['MinBlobSize'], $stat['MaxBlobSize'], (100*$stat['MinBlobSize']/$stat['Area']), (100*$stat['MaxBlobSize']/$stat['Area']) ) ?></td>
<?php
}
else
{
?>
<td class="colBlobSizes"><?php echo sprintf( "%d (%d%%)", $stat['MinBlobSize'], 100*$stat['MinBlobSize']/$stat['Area'] ) ?></td>
<?php
}
?>
<td class="colAlarmLimits"><?php echo validHtmlStr($stat['MinX'].",".$stat['MinY']."-".$stat['MaxX'].",".$stat['MaxY']) ?></td>
<td class="colScore"><?php echo $stat['Score'] ?></td>
</tr>
<?php
}
}
else
{
?>
<tr>
<td class="rowNoStats" colspan="9"><?php echo translate('NoStatisticsRecorded') ?></td>
</tr>
<?php
}
?>
</tbody>
</table>
<?php include('_stats_table.php'); ?>
</form>
</div>
</div>

View File

@ -43,148 +43,125 @@ sub generateConfigFiles
generateConfigSQL();
}
sub generateConfigHeader
{
print( "Generating '$config_header'\n" );
open( CFG_HDR_FILE, ">$config_header" ) or die( "Can't open '$config_header' for writing" );
print( CFG_HDR_FILE "// The file is autogenerated by zmconfgen.pl\n" );
print( CFG_HDR_FILE "// Do not edit this file as any changes will be overwritten\n\n" );
sub generateConfigHeader {
print("Generating '$config_header'\n");
open(CFG_HDR_FILE, '>'.$config_header) or die("Can't open '$config_header' for writing");
print(CFG_HDR_FILE "// The file is autogenerated by zmconfgen.pl\n");
print(CFG_HDR_FILE "// Do not edit this file as any changes will be overwritten\n\n");
my $last_id = 0;
my $define_list = "";
my $declare_list = "";
my $assign_list = "";
foreach my $option ( @options )
{
next if ( !defined($option->{id}) );
my $define_list = '';
my $declare_list = '';
my $assign_list = '';
foreach my $option ( @options ) {
next if !defined($option->{id});
my $opt_id = $option->{id};
my $opt_name = $option->{name};
my $opt_type = $option->{type};
my $var_name = substr( lc($opt_name), 3 );
# If only used in ui, then don't include it in C++ config defines
next if $option->{processes} and ($option->{processes} ne 'web');
$define_list .= sprintf( "#define $opt_name $opt_id\n" );
my $opt_id = $option->{id};
my $opt_name = $option->{name};
my $opt_type = $option->{type};
my $var_name = substr( lc($opt_name), 3 );
$declare_list .= sprintf( "\t" );
if ( $opt_type->{db_type} eq 'boolean' )
{
$declare_list .= sprintf( "bool " );
}
elsif ( $opt_type->{db_type} eq 'integer' || $opt_type->{db_type} eq 'hexadecimal' )
{
$declare_list .= sprintf( "int " );
}
elsif ( $opt_type->{db_type} eq 'decimal' )
{
$declare_list .= sprintf( "double " );
}
else
{
$declare_list .= sprintf( "const char *" );
}
$declare_list .= sprintf( $var_name.";\\\n" );
$define_list .= "#define $opt_name $opt_id\n";
$assign_list .= sprintf( "\t" );
$assign_list .= sprintf( $var_name." = " );
if ( $opt_type->{db_type} eq 'boolean' )
{
$assign_list .= sprintf( "(bool)" );
}
elsif ( $opt_type->{db_type} eq 'integer' || $opt_type->{db_type} eq 'hexadecimal' )
{
$assign_list .= sprintf( "(int)" );
}
elsif ( $opt_type->{db_type} eq 'decimal' )
{
$assign_list .= sprintf( "(double) " );
}
else
{
$assign_list .= sprintf( "(const char *)" );
}
$assign_list .= sprintf( "config.Item( ".$opt_name." );\\\n" );
$declare_list .= "\t";
if ( $opt_type->{db_type} eq 'boolean' ) {
$declare_list .= 'bool ';
} elsif ( $opt_type->{db_type} eq 'integer' || $opt_type->{db_type} eq 'hexadecimal' ) {
$declare_list .= 'int ';
} elsif ( $opt_type->{db_type} eq 'decimal' ) {
$declare_list .= 'double ';
} else {
$declare_list .= 'const char *';
}
$declare_list .= $var_name.";\\\n";
$last_id = $option->{id};
}
print( CFG_HDR_FILE $define_list."\n\n" );
print( CFG_HDR_FILE "#define ZM_MAX_CFG_ID $last_id\n\n" );
print( CFG_HDR_FILE "#define ZM_CFG_DECLARE_LIST \\\n" );
print( CFG_HDR_FILE $declare_list."\n\n" );
print( CFG_HDR_FILE "#define ZM_CFG_ASSIGN_LIST \\\n" );
print( CFG_HDR_FILE $assign_list."\n\n" );
close( CFG_HDR_FILE );
$assign_list .= "\t";
$assign_list .= $var_name.' = ';
if ( $opt_type->{db_type} eq 'boolean' ) {
$assign_list .= '(bool)';
} elsif ( $opt_type->{db_type} eq 'integer' || $opt_type->{db_type} eq 'hexadecimal' ) {
$assign_list .= '(int)';
} elsif ( $opt_type->{db_type} eq 'decimal' ) {
$assign_list .= '(double) ';
} else {
$assign_list .= '(const char *)';
}
$assign_list .= 'config.Item('.$opt_name.");\\\n";
$last_id = $option->{id};
} # end foreach option
print( CFG_HDR_FILE $define_list."\n\n" );
print( CFG_HDR_FILE "#define ZM_MAX_CFG_ID $last_id\n\n" );
print( CFG_HDR_FILE "#define ZM_CFG_DECLARE_LIST \\\n" );
print( CFG_HDR_FILE $declare_list."\n\n" );
print( CFG_HDR_FILE "#define ZM_CFG_ASSIGN_LIST \\\n" );
print( CFG_HDR_FILE $assign_list."\n\n" );
close( CFG_HDR_FILE );
}
sub generateConfigSQL
{
print( "Updating '$config_sql'\n" );
my $config_sql_temp = $config_sql.".temp";
open( CFG_SQL_FILE, "<$config_sql" ) or die( "Can't open '$config_sql' for reading" );
open( CFG_TEMP_SQL_FILE, ">$config_sql_temp" ) or die( "Can't open '$config_sql_temp' for writing" );
while ( my $line = <CFG_SQL_FILE> )
{
last if ( $line =~ /^-- This section is autogenerated/ );
print( CFG_TEMP_SQL_FILE $line );
}
close( CFG_SQL_FILE );
sub generateConfigSQL {
print("Updating '$config_sql'\n");
my $config_sql_temp = $config_sql.'.temp';
open(CFG_SQL_FILE, '<'.$config_sql) or die("Can't open '$config_sql' for reading");
open(CFG_TEMP_SQL_FILE, '>'.$config_sql_temp) or die("Can't open '$config_sql_temp' for writing");
while ( my $line = <CFG_SQL_FILE> ) {
last if ( $line =~ /^-- This section is autogenerated/ );
print(CFG_TEMP_SQL_FILE $line);
}
close(CFG_SQL_FILE);
print( CFG_TEMP_SQL_FILE "-- This section is autogenerated by zmconfgen.pl\n" );
print( CFG_TEMP_SQL_FILE "-- Do not edit this file as any changes will be overwritten\n" );
print( CFG_TEMP_SQL_FILE "--\n\n" );
print( CFG_TEMP_SQL_FILE "delete from Config;\n\n" );
foreach my $option ( @options )
{
#print( $option->{name}."\n" ) if ( !$option->{category} );
$option->{db_type} = $option->{type}->{db_type};
$option->{db_hint} = $option->{type}->{hint};
$option->{db_pattern} = $option->{type}->{pattern};
$option->{db_format} = $option->{type}->{format};
if ( $option->{db_type} eq "boolean" )
{
$option->{db_value} = ($option->{value} eq "yes")?"1":"0";
}
else
{
$option->{db_value} = $option->{value};
}
if ( $option->{name} eq "ZM_DYN_CURR_VERSION" || $option->{name} eq "ZM_DYN_DB_VERSION" )
{
$option->{db_value} = '@VERSION@';
}
if ( my $requires = $option->{requires} )
{
$option->{db_requires} = join( ";", map { my $value = $_->{value}; $value = ($value eq "yes")?1:0 if ( $options_hash{$_->{name}}->{db_type} eq "boolean" ); ( "$_->{name}=$value" ) } @$requires );
}
else
{
$option->{db_requires} = "";
}
printf( CFG_TEMP_SQL_FILE
"insert into Config set Id = %d, Name = '%s', Value = '%s', Type = '%s', DefaultValue = '%s', Hint = '%s', Pattern = '%s', Format = '%s', Prompt = '%s', Help = '%s', Category = '%s', Readonly = '%s', Requires = '%s';\n",
$option->{id},
$option->{name},
addSlashes($option->{db_value}),
$option->{db_type},
addSlashes($option->{default}),
addSlashes($option->{db_hint}),
addSlashes($option->{db_pattern}),
addSlashes($option->{db_format}),
addSlashes($option->{description}),
addSlashes($option->{help}),
$option->{category},
$option->{readonly}?1:0,
$option->{db_requires}
);
}
print( CFG_TEMP_SQL_FILE "\n" );
close( CFG_TEMP_SQL_FILE );
print( CFG_TEMP_SQL_FILE "-- This section is autogenerated by zmconfgen.pl\n" );
print( CFG_TEMP_SQL_FILE "-- Do not edit this file as any changes will be overwritten\n" );
print( CFG_TEMP_SQL_FILE "--\n\n" );
print( CFG_TEMP_SQL_FILE "delete from Config;\n\n" );
foreach my $option ( @options ) {
#print( $option->{name}."\n" ) if ( !$option->{category} );
$option->{db_type} = $option->{type}->{db_type};
$option->{db_hint} = $option->{type}->{hint};
$option->{db_pattern} = $option->{type}->{pattern};
$option->{db_format} = $option->{type}->{format};
my %processes = map { $_ => $_ } split(',', $option->{processes}) if $option->{processes};
if ( $option->{db_type} eq 'boolean' ) {
$option->{db_value} = ($option->{value} eq 'yes') ? '1' : '0';
} else {
$option->{db_value} = $option->{value};
}
if ( $option->{name} eq 'ZM_DYN_CURR_VERSION' || $option->{name} eq 'ZM_DYN_DB_VERSION' ) {
$option->{db_value} = '@VERSION@';
}
if ( my $requires = $option->{requires} ) {
$option->{db_requires} = join(';', map { my $value = $_->{value}; $value = ($value eq 'yes')?1:0 if ( $options_hash{$_->{name}}->{db_type} eq 'boolean' ); ( "$_->{name}=$value" ) } @$requires );
} else {
$option->{db_requires} = '';
}
printf( CFG_TEMP_SQL_FILE
"INSERT INTO Config SET Id = %d, Name = '%s', Value = '%s', Type = '%s', DefaultValue = '%s', Hint = '%s', Pattern = '%s', Format = '%s', Prompt = '%s', Help = '%s', Category = '%s', Readonly = '%s', Requires = '%s';\n",
$option->{id},
$option->{name},
addSlashes($option->{db_value}),
$option->{db_type},
addSlashes($option->{default}),
addSlashes($option->{db_hint}),
addSlashes($option->{db_pattern}),
addSlashes($option->{db_format}),
addSlashes($option->{description}),
addSlashes($option->{help}),
$option->{category},
$option->{readonly}?1:0,
$option->{db_requires}
);
} # end foreach option
print(CFG_TEMP_SQL_FILE "\n");
close(CFG_TEMP_SQL_FILE);
rename( $config_sql_temp, $config_sql ) or die( "Can't rename '$config_sql_temp' to '$config_sql': $!" );
rename( $config_sql_temp, $config_sql ) or die( "Can't rename '$config_sql_temp' to '$config_sql': $!" );
}
sub addSlashes
{
my $string = shift;
return( "" ) if ( !defined($string) );
$string =~ s|(['"])|\\$1|g;
return( $string );
sub addSlashes {
my $string = shift;
return '' if !defined($string);
$string =~ s|(['"])|\\$1|g;
return $string;
}