Merge branch 'master' into improve_filter_emails

This commit is contained in:
Isaac Connor 2020-02-19 14:44:37 -05:00
commit 300402013c
9 changed files with 414 additions and 39 deletions

View File

@ -811,6 +811,7 @@ INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-423','Ffmpeg','Reolink',0,0,1,0
INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-411','Ffmpeg','Reolink',0,0,1,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Reolink RLC-420','Ffmpeg','Reolink',0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'D-LINK DCS-3415','Remote','DCS3415',0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'D-Link DCS-5020L','Remote','DCS5020L',1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,24,1,0,1,1,1,0,1,0,1,0,0,1,30,0,0,0,0,0,1,0,0,1,30,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'IOS Camera','Ffmpeg','IPCAMIOS',0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,1,0,1,0,0,0,0,1,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Dericam P2','Ffmpeg','DericamP2',0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,10,0,1,1,1,0,0,0,1,1,0,0,0,0,1,1,45,0,0,1,0,0,0,0,1,1,45,0,0,0,0);
INSERT INTO `Controls` VALUES (NULL,'Trendnet','Remote','Trendnet',1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,1,1,0,1,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0);
@ -845,6 +846,7 @@ INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, multicast','Remote','rt
INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, RTP/RTSP','Remote','rtsp',0,255,'rtsp','rtpRtsp','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT into MonitorPresets VALUES (NULL,'Axis IP, mpeg4, RTP/RTSP/HTTP','Remote',NULL,NULL,NULL,'rtsp','rtpRtspHttp','<ip-address>',554,'/mpeg4/media.amp','/trackID=',NULL,NULL,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'D-link DCS-930L, 640x480, mjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/mjpeg.cgi',NULL,640,480,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'D-Link DCS-5020L, 640x480, mjpeg','Remote','http',0,0,'http','simple','<username>:<pwd>@<ip-address>','80','/video.cgi',NULL,640,480,0,NULL,1,'34',NULL,'<username>:<pwd>@<ip-address>',100,100);
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, mpjpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/nphMotionJpeg?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, jpeg','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,NULL,0,NULL,NULL,NULL,100,100);
INSERT INTO MonitorPresets VALUES (NULL,'Panasonic IP, 320x240, jpeg, max 5 FPS','Remote','http',0,0,'http','simple','<ip-address>',80,'/SnapshotJPEG?Resolution=320x240&Quality=Standard',NULL,320,240,3,5.0,0,NULL,NULL,NULL,100,100);

5
db/zm_update-1.34.3.sql Normal file
View File

@ -0,0 +1,5 @@
--
-- This updates a 1.34.2 database to 1.34.3
--
-- No changes required
--

View File

@ -28,7 +28,7 @@
%global _hardened_build 1
Name: zoneminder
Version: 1.34.2
Version: 1.34.3
Release: 1%{?dist}
Summary: A camera monitoring and analysis tool
Group: System Environment/Daemons

View File

@ -29,6 +29,7 @@ use Time::HiRes qw( usleep );
require ZoneMinder::Base;
require ZoneMinder::Control;
require LWP::UserAgent;
use URI;
our @ISA = qw(ZoneMinder::Control);
@ -53,24 +54,28 @@ sub open {
my $self = shift;
$self->loadMonitor();
my $username;
my $password;
my $realm = 'Login to ' . $self->{Monitor}->{ControlDevice};
if ( $self->{Monitor}->{ControlAddress} !~ /^\w+:\/\// ) {
# Has no scheme at the beginning, so won't parse as a URI
$self->{Monitor}->{ControlAddress} = 'http://'.$self->{Monitor}->{ControlAddress};
}
my $uri = URI->new($self->{Monitor}->{ControlAddress});
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent('ZoneMinder Control Agent/'.ZoneMinder::Base::ZM_VERSION);
if ( $self->{Monitor}->{ControlAddress} =~ /(.*):(.*)@(.*)/ ) {
$username = $1;
$password = $2;
$$self{address} = $3;
$self->{ua}->credentials($$self{address}, $realm, $username, $password);
my ( $username, $password );
my $realm = 'Login to ' . $self->{Monitor}->{ControlDevice};
if ( $self->{Monitor}->{ControlAddress} ) {
( $username, $password ) = $uri->authority() =~ /^(.*):(.*)@(.*)$/;
$$self{address} = $uri->host_port();
$self->{ua}->credentials($uri->host_port(), $realm, $username, $password);
# Testing seems to show that we need the username/password in each url as well as credentials
$$self{base_url} = 'http://'.$self->{Monitor}->{ControlDevice};
Debug("Using initial credentials for $$self{address}, $realm, $username, $password");
$$self{base_url} = $uri->canonical();
Debug('Using initial credentials for '.$uri->host_port().", $realm, $username, $password, base_url: $$self{base_url} auth:".$uri->authority());
}
# Detect REALM, has to be /cgi-bin/ptz.cgi because just / accepts no auth
my $res = $self->{ua}->get($$self{base_url}.'/cgi-bin/ptz.cgi');
my $res = $self->{ua}->get($$self{base_url}.'cgi-bin/ptz.cgi');
if ( $res->is_success ) {
$self->{state} = 'open';
@ -91,7 +96,7 @@ sub open {
$realm = $1;
Debug("Changing REALM to ($realm)");
$self->{ua}->credentials($$self{address}, $realm, $username, $password);
$res = $self->{ua}->get($$self{address}.'/cgi-bin/ptz.cgi');
$res = $self->{ua}->get($$self{base_url}.'cgi-bin/ptz.cgi');
if ( $res->is_success() ) {
$self->{state} = 'open';
return;
@ -116,7 +121,7 @@ sub open {
Debug('No headers line');
} # end if headers
} else {
Error("Failed to get $$self{address}/cgi-bin/ptz.cgi ".$res->status_line());
Error("Failed to get $$self{base_url}cgi-bin/ptz.cgi ".$res->status_line());
} # end if $res->status_line() eq '401 Unauthorized'
@ -135,21 +140,21 @@ sub sendCmd {
$self->printMsg($cmd, 'Tx');
my $res = $self->{ua}->get("http://$$self{address}/$cmd");
my $res = $self->{ua}->get($$self{base_url}.$cmd);
if ( $res->is_success ) {
$result = !undef;
# Command to camera appears successful, write Info item to log
Info('Camera control: \''.$res->status_line().'\' for URL '.$$self{address}.'/'.$cmd);
Info('Camera control: \''.$res->status_line().'\' for URL '.$$self{base_url}.$cmd);
# TODO: Add code to retrieve $res->message_decode or some such. Then we could do things like check the camera status.
} else {
# Try again
$res = $self->{ua}->get("http://$$self{address}/$cmd");
$res = $self->{ua}->get($$self{base_url}.$cmd);
if ( $res->is_success ) {
# Command to camera appears successful, write Info item to log
Info('Camera control: \''.$res->status_line().'\' for URL '.$$self{address}.'/'.$cmd);
Info('Camera control 2: \''.$res->status_line().'\' for URL '.$$self{base_url}.$cmd);
} else {
Error('Camera control command FAILED: \''.$res->status_line().'\' for URL '.$$self{address}.'/'.$cmd);
Error('Camera control command FAILED: \''.$res->status_line().'\' for URL '.$$self{base_url}.$cmd);
$res = $self->{ua}->get('http://'.$self->{Monitor}->{ControlAddress}.'/'.$cmd);
}
}

View File

@ -0,0 +1,356 @@
# =========================================================================r
#
# ZoneMinder D-Link DCS-5020L IP Control Protocol Module, $Date: $, $Revision: $
# Copyright (C) 2013 Art Scheel
#
# 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# ==========================================================================
#
# This module contains the implementation of the D-Link DCS-5020L IP camera control
# protocol.
#
package ZoneMinder::Control::DCS5020L;
use 5.006;
use strict;
use warnings;
require ZoneMinder::Base;
require ZoneMinder::Control;
our @ISA = qw(ZoneMinder::Control);
our $VERSION = $ZoneMinder::Base::VERSION;
# ==========================================================================
#
# D-Link DCS-5020L Control Protocol
#
# ==========================================================================
use ZoneMinder::Logger qw(:all);
use ZoneMinder::Config qw(:all);
use Time::HiRes qw( usleep );
sub new
{
my $class = shift;
my $id = shift;
my $self = ZoneMinder::Control->new( $id );
bless( $self, $class );
srand( time() );
return $self;
}
our $AUTOLOAD;
sub AUTOLOAD
{
my $self = shift;
my $class = ref($self) || croak( "$self not object" );
my $name = $AUTOLOAD;
$name =~ s/.*://;
if ( exists($self->{$name}) )
{
return( $self->{$name} );
}
Fatal( "Can't access $name member of object of class $class" );
}
sub open
{
my $self = shift;
$self->loadMonitor();
use LWP::UserAgent;
$self->{ua} = LWP::UserAgent->new;
$self->{ua}->agent( "ZoneMinder Control Agent/" . ZoneMinder::Base::ZM_VERSION );
$self->{state} = 'open';
}
sub close
{
my $self = shift;
$self->{state} = 'closed';
}
sub printMsg
{
my $self = shift;
my $msg = shift;
my $msg_len = length($msg);
Debug( $msg."[".$msg_len."]" );
}
sub sendCmd
{
my $self = shift;
my $cmd = shift;
my $cgi = shift;
my $result = undef;
printMsg( $cmd, "Tx" );
my $req = HTTP::Request->new( POST=>"http://$self->{Monitor}->{ControlAddress}/$cgi.cgi" );
$req->content($cmd);
my $res = $self->{ua}->request($req);
if ( $res->is_success )
{
$result = !undef;
}
else
{
Error( "Error check failed: '".$res->status_line()."'" );
}
return( $result );
}
sub move
{
my $self = shift;
my $dir = shift;
my $panStep = shift;
my $tiltStep = shift;
my $cmd = "PanSingleMoveDegree=$panStep&TiltSingleMoveDegree=$tiltStep&PanTiltSingleMove=$dir";
$self->sendCmd( $cmd, 'pantiltcontrol' );
}
sub moveRel
{
my $self = shift;
my $params = shift;
my $panStep = $self->getParam($params, 'panstep', 0);
my $tiltStep = $self->getParam($params, 'tiltstep', 0);
my $dir = shift;
$self->move( $dir, $panStep, $tiltStep );
}
sub moveRelUpLeft
{
my $self = shift;
my $params = shift;
$self->moveRel( $params, 0 );
}
sub moveRelUp
{
my $self = shift;
my $params = shift;
$self->moveRel( $params, 1 );
}
sub moveRelUpRight
{
my $self = shift;
my $params = shift;
$self->moveRel( $params, 2 );
}
sub moveRelLeft
{
my $self = shift;
my $params = shift;
$self->moveRel( $params, 3 );
}
sub moveRelRight
{
my $self = shift;
my $params = shift;
$self->moveRel( $params, 5 );
}
sub moveRelDownLeft
{
my $self = shift;
my $params = shift;
$self->moveRel( $params, 6 );
}
sub moveRelDown
{
my $self = shift;
my $params = shift;
$self->moveRel( $params, 7 );
}
sub moveRelDownRight
{
my $self = shift;
my $params = shift;
$self->moveRel( $params, 8 );
}
# moves the camera to center on the point that the user clicked on in the video image.
# This isn't extremely accurate but good enough for most purposes
sub moveMap
{
# if the camera moves too much or too little, try increasing or decreasing this value
my $f = 11;
my $self = shift;
my $params = shift;
my $xcoord = $self->getParam( $params, 'xcoord' );
my $ycoord = $self->getParam( $params, 'ycoord' );
my $hor = $xcoord * 100 / $self->{Monitor}->{Width};
my $ver = $ycoord * 100 / $self->{Monitor}->{Height};
my $direction;
my $horSteps;
my $verSteps;
if ($hor < 50 && $ver < 50) {
# up left
$horSteps = (50 - $hor) / $f;
$verSteps = (50 - $ver) / $f;
$direction = 0;
} elsif ($hor >= 50 && $ver < 50) {
# up right
$horSteps = ($hor - 50) / $f;
$verSteps = (50 - $ver) / $f;
$direction = 2;
} elsif ($hor < 50 && $ver >= 50) {
# down left
$horSteps = (50 - $hor) / $f;
$verSteps = ($ver - 50) / $f;
$direction = 6;
} elsif ($hor >= 50 && $ver >= 50) {
# down right
$horSteps = ($hor - 50) / $f;
$verSteps = ($ver - 50) / $f;
$direction = 8;
}
my $v = int($verSteps + .5);
my $h = int($horSteps + .5);
Debug( "Move Map to $xcoord,$ycoord, hor=$h, ver=$v with direction $direction" );
$self->move( $direction, $h, $v );
}
sub presetClear
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Clear Preset $preset" );
my $cmd = "ClearPosition=$preset";
$self->sendCmd( $cmd, 'pantiltcontrol' );
}
sub presetSet
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Set Preset $preset" );
my $cmd = "SetCurrentPosition=$preset&SetName=preset_$preset";
$self->sendCmd( $cmd, 'pantiltcontrol' );
}
sub presetGoto
{
my $self = shift;
my $params = shift;
my $preset = $self->getParam( $params, 'preset' );
Debug( "Goto Preset $preset" );
my $cmd = "PanTiltPresetPositionMove=$preset";
$self->sendCmd( $cmd, 'pantiltcontrol' );
}
sub presetHome
{
my $self = shift;
Debug( "Home Preset" );
$self->move( 4, 0, 0 );
}
# IR Controls
#
# wake = IR on
# sleep = IR off
# reset = IR auto
sub setDayNightMode {
my $self = shift;
my $mode = shift;
my $cmd = "DayNightMode=$mode&ConfigReboot=No";
$self->sendCmd( $cmd, 'daynight' );
}
sub wake
{
my $self = shift;
Debug( "Wake - IR on" );
$self->setDayNightMode(2);
}
sub sleep
{
my $self = shift;
Debug( "Sleep - IR off" );
$self->setDayNightMode(3);
}
sub reset
{
my $self = shift;
Debug( "Reset - IR auto" );
$self->setDayNightMode(0);
}
1;
__END__
# Below is stub documentation for your module. You'd better edit it!
=head1 NAME
ZoneMinder::Database - Perl extension for DCS-5020L
=head1 SYNOPSIS
use ZoneMinder::Database;
DLINK DCS-5020L
=head1 DESCRIPTION
ZoneMinder driver for the D-Link consumer camera DCS-5020L.
=head2 EXPORT
None by default.
=head1 SEE ALSO
See if there are better instructions for the DCS-5020L at
http://www.zoneminder.com/wiki/index.php/Dlink
=head1 AUTHOR
Art Scheel <lt>ascheel (at) gmail<gt>
=head1 COPYRIGHT AND LICENSE
LGPLv3
=cut

View File

@ -95,9 +95,9 @@ sub PutCmd {
my $self = shift;
my $cmd = shift;
my $content = shift;
my $req = HTTP::Request->new(PUT => "$self->{BaseURL}/$cmd");
my $req = HTTP::Request->new(PUT => $self->{BaseURL}.'/'.$cmd);
if ( defined($content) ) {
$req->content_type("application/x-www-form-urlencoded; charset=UTF-8");
$req->content_type('application/x-www-form-urlencoded; charset=UTF-8');
$req->content('<?xml version="1.0" encoding="UTF-8"?>' . "\n" . $content);
}
my $res = $self->{UA}->request($req);
@ -135,13 +135,13 @@ sub PutCmd {
# Check for username/password
#
if ( $self->{Monitor}{ControlAddress} =~ /.+:(.+)@.+/ ) {
Info("Check username/password is correct");
Info('Check username/password is correct');
} elsif ( $self->{Monitor}{ControlAddress} =~ /^[^:]+@.+/ ) {
Info("No password in Control Address. Should there be one?");
Info('No password in Control Address. Should there be one?');
} elsif ( $self->{Monitor}{ControlAddress} =~ /^:.+@.+/ ) {
Info("Password but no username in Control Address.");
Info('Password but no username in Control Address.');
} else {
Info("Missing username and password in Control Address.");
Info('Missing username and password in Control Address.');
}
Fatal($res->status_line);
}
@ -382,7 +382,7 @@ sub irisRelOpen {
sub reset {
my $self = shift;
$self->PutCmd("ISAPI/System/reboot");
$self->PutCmd('ISAPI/System/reboot');
}
1;

View File

@ -352,10 +352,13 @@ sub exportsql {
}
my $name = $ARGV[0];
if ($name) {
$name =~ /([A-Za-z0-9 -]*)/; # Only allow alphanumeric, dash and space
$name = $1;
$command .= qq( --where="Name = '$name'");
if ( $name ) {
if ( $name =~ /^([A-Za-z0-9 ,.&()\/\-]+)$/ ) { # Allow alphanumeric and " ,.&()/-"
$name = $1;
$command .= qq( --where="Name = '$name'");
} else {
print "Invalid characters in Name\n";
}
}
$command .= " zm Controls MonitorPresets";

View File

@ -1 +1 @@
1.34.2
1.34.3

View File

@ -167,18 +167,18 @@ function parseRows(rows) {
}
var brackets = rows.length - 2;
if (brackets > 0) { //add bracket select to all rows
if ( brackets > 0 ) { // add bracket select to all rows
var obrSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][obr]').attr('id', queryPrefix + rowNum + '][obr]');
var cbrSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][cbr]').attr('id', queryPrefix + rowNum + '][cbr]');
obrSelect.append('<option value="0"</option>');
cbrSelect.append('<option value="0"</option>');
for (var i = 1; i <= brackets; i++) {//build bracket options
for ( var i = 1; i <= brackets; i++ ) { // build bracket options
obrSelect.append('<option value="' + i + '">' + '('.repeat(i) + '</option>');
cbrSelect.append('<option value="' + i + '">' + ')'.repeat(i) + '</option>');
}
var obrVal = inputTds.eq(1).children().val() != undefined ? inputTds.eq(1).children().val() : 0; //Save currently selected bracket option
var obrVal = inputTds.eq(1).children().val() != undefined ? inputTds.eq(1).children().val() : 0; // Save currently selected bracket option
var cbrVal = inputTds.eq(5).children().val() != undefined ? inputTds.eq(5).children().val() : 0;
inputTds.eq(1).html(obrSelect).children().val(obrVal); //Set bracket contents and assign saved value
inputTds.eq(1).html(obrSelect).children().val(obrVal); // Set bracket contents and assign saved value
inputTds.eq(5).html(cbrSelect).children().val(cbrVal);
} else {
inputTds.eq(1).html('&nbsp'); // Blank if there aren't enough terms for brackets
@ -186,14 +186,13 @@ function parseRows(rows) {
}
if ( rows.length == 1 ) {
inputTds.eq(6).find('button[data-on-click-this="delTerm"]').prop('disabled', true); //enable/disable remove row button
inputTds.eq(6).find('button[data-on-click-this="delTerm"]').prop('disabled', true); // enable/disable remove row button
} else {
inputTds.eq(6).find('button[data-on-click-this="delTerm"]').prop('disabled', false);
}
var attr = inputTds.eq(2).children().val();
if ( attr == "Archived" ) { //Archived types
if ( attr == 'Archived' ) { // Archived types
inputTds.eq(3).html('equal to<input type="hidden" name="filter[Query][terms][' + rowNum + '][op]" value="=">');
var archiveSelect = $j('<select></select>').attr('name', queryPrefix + rowNum + '][val]').attr('id', queryPrefix + rowNum + '][val]');
for (var i = 0; i < archiveTypes.length; i++) {
@ -283,11 +282,16 @@ function addTerm( element ) {
this[0].selected = 'selected';
}).chosen({width: '101%'});
newRow.find('input[type="text"]').val('');
newRow[0].querySelectorAll("button[data-on-click-this]").forEach(function attachOnClick(el) {
newRow[0].querySelectorAll("button[data-on-click-this]").forEach(function(el) {
var fnName = el.getAttribute("data-on-click-this");
el.onclick = window[fnName].bind(el, el);
});
newRow[0].querySelectorAll('select[data-on-change-this]').forEach(function(el) {
var fnName = el.getAttribute('data-on-change-this');
el.onchange = window[fnName].bind(el, el);
});
var rows = $j(row).parent().children();
parseRows(rows);
}