diff --git a/.gitignore b/.gitignore index 65d6949..289210e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ .vagrant venv +venv2 .vscode .idea .DS_* diff --git a/.travis.yml b/.travis.yml index 747a498..e012921 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,8 +1,8 @@ language: python python: - - "2.7" + - "3.6" env: - - DJANGO=1.11.26 + - DJANGO=2.2.10 install: - pip install -r dev/requirements.txt script: diff --git a/Dockerfile b/Dockerfile index 0c04c68..c3b122f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,21 +6,21 @@ RUN echo 'APT::Get::Clean=always;' >> /etc/apt/apt.conf.d/99AutomaticClean RUN apt-get update -qqy RUN DEBIAN_FRONTEND=noninteractive apt-get -qyy install \ -o APT::Install-Suggests=false \ - git python-virtualenv python-dev python-lxml libvirt-dev zlib1g-dev nginx libsasl2-modules + git python3-virtualenv python3-dev python3-lxml virtualenv libvirt-dev zlib1g-dev nginx libsasl2-modules ADD . /srv/webvirtcloud RUN chown -R www-data:www-data /srv/webvirtcloud # Setup webvirtcloud RUN cd /srv/webvirtcloud && \ - virtualenv venv && \ + virtualenv --python=python3 venv && \ . venv/bin/activate && \ - pip install -U pip && \ - pip install -r conf/requirements.txt && \ + pip3 install -U pip && \ + pip3 install -r conf/requirements.txt && \ chown -R www-data:www-data /srv/webvirtcloud RUN cd /srv/webvirtcloud && . venv/bin/activate && \ - python manage.py migrate && \ + python3 manage.py migrate && \ chown -R www-data:www-data /srv/webvirtcloud # Setup Nginx diff --git a/README.md b/README.md index 6d810b5..1b2fcb2 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ## WebVirtCloud - +###### Python3 & Django 2.11 ## Features * QEMU/KVM Hypervisor Management @@ -38,10 +38,10 @@ haystack = string.ascii_letters + string.digits + string.punctuation print(''.join([random.SystemRandom().choice(haystack) for _ in range(50)])) ``` -### Install WebVirtCloud panel (Ubuntu) +### Install WebVirtCloud panel (Ubuntu 18.04+ LTS) ```bash -sudo apt-get -y install git virtualenv python-virtualenv python-dev python-lxml libvirt-dev zlib1g-dev libxslt1-dev nginx supervisor libsasl2-modules gcc pkg-config python-guestfs +sudo apt-get -y install git virtualenv python3-virtualenv python3-dev python3-lxml libvirt-dev zlib1g-dev libxslt1-dev nginx supervisor libsasl2-modules gcc pkg-config python3-guestfs git clone https://github.com/retspen/webvirtcloud cd webvirtcloud cp webvirtcloud/settings.py.template webvirtcloud/settings.py @@ -52,7 +52,7 @@ cd .. sudo mv webvirtcloud /srv sudo chown -R www-data:www-data /srv/webvirtcloud cd /srv/webvirtcloud -virtualenv venv +virtualenv -p python3 venv source venv/bin/activate pip install -r conf/requirements.txt python manage.py migrate @@ -76,11 +76,11 @@ Done!! Go to http://serverip and you should see the login screen. - -### Install WebVirtCloud panel (CentOS) +### Install WebVirtCloud panel (CentOS8/OEL8) ```bash -sudo yum -y install python-virtualenv python-devel libvirt-devel glibc gcc nginx supervisor python-lxml git python-libguestfs iproute-tc +sudo yum -y install epel-release +sudo yum -y install python3-virtualenv python3-devel libvirt-devel glibc gcc nginx supervisor python3-lxml git python3-libguestfs iproute-tc cyrus-sasl-md5 python3-libguestfs ``` #### Creating directories and cloning repo @@ -90,15 +90,17 @@ sudo mkdir /srv && cd /srv sudo git clone https://github.com/retspen/webvirtcloud && cd webvirtcloud cp webvirtcloud/settings.py.template webvirtcloud/settings.py # now put secret key to webvirtcloud/settings.py +# create secret key manually or use that command +sudo sed -r "s/SECRET_KEY = ''/SECRET_KEY = '"`python3 /srv/webvirtcloud/conf/runit/secret_generator.py`"'/" -i /srv/webvirtcloud/webvirtcloud/settings.py ``` #### Start installation webvirtcloud ``` -sudo virtualenv venv -sudo source venv/bin/activate -sudo venv/bin/pip install -r conf/requirements.txt -sudo cp conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/ -sudo venv/bin/python manage.py migrate +virtualenv-3 venv +source venv/bin/activate +pip3 install -r conf/requirements.txt +cp conf/nginx/webvirtcloud.conf /etc/nginx/conf.d/ +python3 manage.py migrate ``` #### Configure the supervisor for CentOS @@ -115,7 +117,7 @@ autorestart=true redirect_stderr=true [program:novncd] -command=/srv/webvirtcloud/venv/bin/python /srv/webvirtcloud/console/novncd +command=/srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/console/novncd directory=/srv/webvirtcloud user=nginx autostart=true @@ -191,11 +193,20 @@ Change permission for selinux: ```bash sudo semanage fcontext -a -t httpd_sys_content_t "/srv/webvirtcloud(/.*)" +sudo setsebool -P httpd_can_network_connect on -P ``` -Add required user to the kvm group: +Add required user to the kvm group(if you not install with root): ```bash -sudo usermod -G kvm -a webvirtmgr +sudo usermod -G kvm -a <username> +``` + +Allow http ports on firewall: +```bash +sudo firewall-cmd --add-service=http +sudo firewall-cmd --add-service=http --permanent +sudo firewall-cmd --add-port=6080/tcp +sudo firewall-cmd --add-port=6080/tcp --permanent ``` Let's restart nginx and the supervisord services: @@ -226,7 +237,7 @@ Done!! Go to http://serverip and you should see the login screen. -### Alternative running novncd via runit +### Alternative running novncd via runit(Debian) Alternative to running nonvcd via supervisor is runit. On Debian systems install runit and configure novncd service @@ -272,11 +283,12 @@ datasource: ### How To Update ```bash -cd <installation-directory> -sudo source venv/bin/activate +# Go to Installation Directory +cd /srv/webvirtcloud +source venv/bin/activate git pull -pip install -U -r conf/requirements.txt -python manage.py migrate +pip3 install -U -r conf/requirements.txt +python3 manage.py migrate sudo service supervisor restart ``` ### Screenshots diff --git a/Vagrantfile b/Vagrantfile index 21819f3..d92377c 100644 --- a/Vagrantfile +++ b/Vagrantfile @@ -12,10 +12,10 @@ Vagrant.configure(2) do |config| sudo sed -i 's/auth_tcp = \"sasl\"/auth_tcp = \"none\"/g' /etc/libvirt/libvirtd.conf sudo service libvirt-bin restart sudo adduser vagrant libvirtd - sudo apt-get -y install python-virtualenv python-dev python-lxml libvirt-dev zlib1g-dev - virtualenv /vagrant/venv + sudo apt-get -y install python3-virtualenv virtualenv python3-pip python3-dev python3-lxml libvirt-dev zlib1g-dev python3-guestfs + virtualenv -p python3 /vagrant/venv source /vagrant/venv/bin/activate - pip install -r /vagrant/dev/requirements.txt + pip3 install -r /vagrant/dev/requirements.txt SHELL end # To start this machine run "vagrant up prod" @@ -24,6 +24,7 @@ Vagrant.configure(2) do |config| prod.vm.box = "ubuntu/bionic64" prod.vm.hostname = "webvirtcloud" prod.vm.network "private_network", ip: "192.168.33.11" + prod.vm.network "forwarded_port", guest: 80, host: 8081 #prod.vm.synced_folder ".", "/srv/webvirtcloud" prod.vm.provision "shell", inline: <<-SHELL sudo mkdir /srv/webvirtcloud @@ -33,15 +34,15 @@ Vagrant.configure(2) do |config| sudo service libvirt-bin restart sudo adduser vagrant libvirtd sudo chown -R vagrant:vagrant /srv/webvirtcloud - sudo apt-get -y install python-virtualenv python-dev python-lxml python-pip libvirt-dev zlib1g-dev libxslt1-dev nginx supervisor libsasl2-modules gcc pkg-config python-guestfs - virtualenv /srv/webvirtcloud/venv + sudo apt-get -y install python3-virtualenv python3-dev python3-lxml python3-pip virtualenv libvirt-dev zlib1g-dev libxslt1-dev nginx supervisor libsasl2-modules gcc pkg-config python3-guestfs + virtualenv -p python3 /srv/webvirtcloud/venv source /srv/webvirtcloud/venv/bin/activate - pip install -r /srv/webvirtcloud/dev/requirements.txt + pip3 install -r /srv/webvirtcloud/requirements.txt sudo cp /srv/webvirtcloud/conf/supervisor/webvirtcloud.conf /etc/supervisor/conf.d sudo cp /srv/webvirtcloud/conf/nginx/webvirtcloud.conf /etc/nginx/conf.d sudo cp /srv/webvirtcloud/webvirtcloud/settings.py.template /srv/webvirtcloud/webvirtcloud/settings.py - sudo sed "s/SECRET_KEY = ''/SECRET_KEY = '"`python /srv/webvirtcloud/conf/runit/secret_generator.py`"'/" -i /srv/webvirtcloud/webvirtcloud/settings.py - python /srv/webvirtcloud/manage.py migrate + sudo sed "s/SECRET_KEY = ''/SECRET_KEY = '"`python3 /srv/webvirtcloud/conf/runit/secret_generator.py`"'/" -i /srv/webvirtcloud/webvirtcloud/settings.py + python3 /srv/webvirtcloud/manage.py migrate sudo rm /etc/nginx/sites-enabled/default sudo chown -R www-data:www-data /srv/webvirtcloud sudo service nginx restart diff --git a/accounts/forms.py b/accounts/forms.py index 4127ac4..db53ed5 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -9,7 +9,8 @@ class UserAddForm(forms.Form): name = forms.CharField(label="Name", error_messages={'required': _('No User name has been entered')}, max_length=20) - password = forms.CharField(required=not settings.ALLOW_EMPTY_PASSWORD, error_messages={'required': _('No password has been entered')},) + password = forms.CharField(required=not settings.ALLOW_EMPTY_PASSWORD, + error_messages={'required': _('No password has been entered')},) def clean_name(self): name = self.cleaned_data['name'] diff --git a/accounts/migrations/0001_initial.py b/accounts/migrations/0001_initial.py index 3989532..1990eeb 100644 --- a/accounts/migrations/0001_initial.py +++ b/accounts/migrations/0001_initial.py @@ -1,29 +1,51 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals +# Generated by Django 2.2.10 on 2020-01-28 07:01 -from django.db import models, migrations from django.conf import settings +import django.core.validators +from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('instances', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ + migrations.CreateModel( + name='UserSSHKey', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('keyname', models.CharField(max_length=25)), + ('keypublic', models.CharField(max_length=500)), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL)), + ], + ), migrations.CreateModel( name='UserInstance', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('is_change', models.BooleanField(default=False)), ('is_delete', models.BooleanField(default=False)), - ('instance', models.ForeignKey(to='instances.Instance')), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), + ('is_vnc', models.BooleanField(default=False)), + ('instance', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='instances.Instance')), + ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ], + ), + migrations.CreateModel( + name='UserAttributes', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('can_clone_instances', models.BooleanField(default=True)), + ('max_instances', models.IntegerField(default=1, help_text='-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)])), + ('max_cpus', models.IntegerField(default=1, help_text='-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)])), + ('max_memory', models.IntegerField(default=2048, help_text='-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)])), + ('max_disk_size', models.IntegerField(default=20, help_text='-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)])), + ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), ], - options={ - }, - bases=(models.Model,), ), ] diff --git a/accounts/migrations/0002_auto_20150325_0846.py b/accounts/migrations/0002_auto_20150325_0846.py deleted file mode 100644 index 8780f97..0000000 --- a/accounts/migrations/0002_auto_20150325_0846.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations - - -def add_useradmin(apps, schema_editor): - from django.utils import timezone - from django.contrib.auth.models import User - - User.objects.create_superuser('admin', None, 'admin', - last_login=timezone.now() - ) - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0001_initial'), - ] - - operations = [ - migrations.RunPython(add_useradmin), - ] diff --git a/accounts/migrations/0003_usersshkey.py b/accounts/migrations/0003_usersshkey.py deleted file mode 100644 index b00bc62..0000000 --- a/accounts/migrations/0003_usersshkey.py +++ /dev/null @@ -1,25 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -from django.conf import settings - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('accounts', '0002_auto_20150325_0846'), - ] - - operations = [ - migrations.CreateModel( - name='UserSSHKey', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('keyname', models.CharField(max_length=25)), - ('keypublic', models.CharField(max_length=500)), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/accounts/migrations/0004_userattributes.py b/accounts/migrations/0004_userattributes.py deleted file mode 100644 index fb32539..0000000 --- a/accounts/migrations/0004_userattributes.py +++ /dev/null @@ -1,26 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -from django.conf import settings - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('accounts', '0003_usersshkey'), - ] - - operations = [ - migrations.CreateModel( - name='UserAttributes', - fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('max_instances', models.IntegerField(default=0)), - ('max_cpus', models.IntegerField(default=0)), - ('max_memory', models.IntegerField(default=0)), - ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL)), - ], - ), - ] diff --git a/accounts/migrations/0004_userinstance_is_vnc.py b/accounts/migrations/0004_userinstance_is_vnc.py deleted file mode 100644 index 9c1c9b8..0000000 --- a/accounts/migrations/0004_userinstance_is_vnc.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0003_usersshkey'), - ] - - operations = [ - migrations.AddField( - model_name='userinstance', - name='is_vnc', - field=models.BooleanField(default=False), - ), - ] diff --git a/accounts/migrations/0005_userattributes_can_clone_instances.py b/accounts/migrations/0005_userattributes_can_clone_instances.py deleted file mode 100644 index 4539657..0000000 --- a/accounts/migrations/0005_userattributes_can_clone_instances.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0004_userattributes'), - ] - - operations = [ - migrations.AddField( - model_name='userattributes', - name='can_clone_instances', - field=models.BooleanField(default=False), - ), - ] diff --git a/accounts/migrations/0006_userattributes_max_disk_size.py b/accounts/migrations/0006_userattributes_max_disk_size.py deleted file mode 100644 index 3d21f5f..0000000 --- a/accounts/migrations/0006_userattributes_max_disk_size.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0005_userattributes_can_clone_instances'), - ] - - operations = [ - migrations.AddField( - model_name='userattributes', - name='max_disk_size', - field=models.IntegerField(default=0), - ), - ] diff --git a/accounts/migrations/0007_auto_20160426_0635.py b/accounts/migrations/0007_auto_20160426_0635.py deleted file mode 100644 index 2f92aba..0000000 --- a/accounts/migrations/0007_auto_20160426_0635.py +++ /dev/null @@ -1,34 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0006_userattributes_max_disk_size'), - ] - - operations = [ - migrations.AlterField( - model_name='userattributes', - name='max_cpus', - field=models.IntegerField(default=1), - ), - migrations.AlterField( - model_name='userattributes', - name='max_disk_size', - field=models.IntegerField(default=20), - ), - migrations.AlterField( - model_name='userattributes', - name='max_instances', - field=models.IntegerField(default=1), - ), - migrations.AlterField( - model_name='userattributes', - name='max_memory', - field=models.IntegerField(default=2048), - ), - ] diff --git a/accounts/migrations/0008_merge.py b/accounts/migrations/0008_merge.py deleted file mode 100644 index 8edf672..0000000 --- a/accounts/migrations/0008_merge.py +++ /dev/null @@ -1,15 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0004_userinstance_is_vnc'), - ('accounts', '0007_auto_20160426_0635'), - ] - - operations = [ - ] diff --git a/accounts/migrations/0009_auto_20171026_0805.py b/accounts/migrations/0009_auto_20171026_0805.py deleted file mode 100644 index 7d035c7..0000000 --- a/accounts/migrations/0009_auto_20171026_0805.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0008_merge'), - ] - - operations = [ - migrations.AlterField( - model_name='userattributes', - name='can_clone_instances', - field=models.BooleanField(default=True), - ), - ] diff --git a/accounts/migrations/0010_auto_20180625_1236.py b/accounts/migrations/0010_auto_20180625_1236.py deleted file mode 100644 index 23e1548..0000000 --- a/accounts/migrations/0010_auto_20180625_1236.py +++ /dev/null @@ -1,35 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.13 on 2018-06-25 12:36 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0009_auto_20171026_0805'), - ] - - operations = [ - migrations.AlterField( - model_name='userattributes', - name='max_cpus', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value'), - ), - migrations.AlterField( - model_name='userattributes', - name='max_disk_size', - field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value'), - ), - migrations.AlterField( - model_name='userattributes', - name='max_instances', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value'), - ), - migrations.AlterField( - model_name='userattributes', - name='max_memory', - field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value'), - ), - ] diff --git a/accounts/migrations/0011_auto_20180625_1313.py b/accounts/migrations/0011_auto_20180625_1313.py deleted file mode 100644 index 1ee194b..0000000 --- a/accounts/migrations/0011_auto_20180625_1313.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.13 on 2018-06-25 13:13 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0010_auto_20180625_1236'), - ] - - operations = [ - migrations.AlterField( - model_name='userattributes', - name='max_cpus', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_disk_size', - field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_instances', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_memory', - field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), - ), - ] diff --git a/accounts/migrations/0012_auto_20180625_1331.py b/accounts/migrations/0012_auto_20180625_1331.py deleted file mode 100644 index 827599e..0000000 --- a/accounts/migrations/0012_auto_20180625_1331.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.13 on 2018-06-25 13:31 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models -import re - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0011_auto_20180625_1313'), - ] - - operations = [ - migrations.AlterField( - model_name='userattributes', - name='max_cpus', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.')]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_disk_size', - field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.')]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_instances', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.')]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_memory', - field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.')]), - ), - ] diff --git a/accounts/migrations/0013_auto_20180625_1358.py b/accounts/migrations/0013_auto_20180625_1358.py deleted file mode 100644 index 1fdec50..0000000 --- a/accounts/migrations/0013_auto_20180625_1358.py +++ /dev/null @@ -1,37 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.13 on 2018-06-25 13:58 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models -import re - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0012_auto_20180625_1331'), - ] - - operations = [ - migrations.AlterField( - model_name='userattributes', - name='max_cpus', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.'), django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_disk_size', - field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.'), django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_instances', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.'), django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_memory', - field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.RegexValidator(re.compile('^-?\\d+\\Z'), code='invalid', message='Enter a valid integer.'), django.core.validators.MinValueValidator(-1)]), - ), - ] diff --git a/accounts/migrations/0014_auto_20180808_1436.py b/accounts/migrations/0014_auto_20180808_1436.py deleted file mode 100644 index a4f3c78..0000000 --- a/accounts/migrations/0014_auto_20180808_1436.py +++ /dev/null @@ -1,36 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.13 on 2018-08-08 11:36 -from __future__ import unicode_literals - -import django.core.validators -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0013_auto_20180625_1358'), - ] - - operations = [ - migrations.AlterField( - model_name='userattributes', - name='max_cpus', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_disk_size', - field=models.IntegerField(default=20, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_instances', - field=models.IntegerField(default=1, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), - ), - migrations.AlterField( - model_name='userattributes', - name='max_memory', - field=models.IntegerField(default=2048, help_text=b'-1 for unlimited. Any integer value', validators=[django.core.validators.MinValueValidator(-1)]), - ), - ] diff --git a/accounts/migrations/0015_auto_20180808_1449.py b/accounts/migrations/0015_auto_20180808_1449.py deleted file mode 100644 index d94905a..0000000 --- a/accounts/migrations/0015_auto_20180808_1449.py +++ /dev/null @@ -1,22 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.13 on 2018-08-08 11:49 -from __future__ import unicode_literals - -from django.conf import settings -from django.db import migrations, models -import django.db.models.deletion - - -class Migration(migrations.Migration): - - dependencies = [ - ('accounts', '0014_auto_20180808_1436'), - ] - - operations = [ - migrations.AlterField( - model_name='usersshkey', - name='user', - field=models.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, to=settings.AUTH_USER_MODEL), - ), - ] diff --git a/accounts/models.py b/accounts/models.py index 42c8051..77cf81a 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -1,36 +1,39 @@ -from django.db import models +from django.db.models import Model, BooleanField, IntegerField, CharField +from django.db.models import ForeignKey, OneToOneField +from django.db.models import CASCADE, DO_NOTHING from django.contrib.auth.models import User from django.conf import settings from instances.models import Instance from django.core.validators import MinValueValidator -class UserInstance(models.Model): - user = models.ForeignKey(User, on_delete=models.CASCADE) - instance = models.ForeignKey(Instance, on_delete=models.CASCADE) - is_change = models.BooleanField(default=False) - is_delete = models.BooleanField(default=False) - is_vnc = models.BooleanField(default=False) +class UserInstance(Model): + user = ForeignKey(User, on_delete=CASCADE) + instance = ForeignKey(Instance, on_delete=CASCADE) + is_change = BooleanField(default=False) + is_delete = BooleanField(default=False) + is_vnc = BooleanField(default=False) def __unicode__(self): return self.instance.name -class UserSSHKey(models.Model): - user = models.ForeignKey(User, on_delete=models.DO_NOTHING) - keyname = models.CharField(max_length=25) - keypublic = models.CharField(max_length=500) +class UserSSHKey(Model): + user = ForeignKey(User, on_delete=DO_NOTHING) + keyname = CharField(max_length=25) + keypublic = CharField(max_length=500) def __unicode__(self): return self.keyname -class UserAttributes(models.Model): - user = models.OneToOneField(User, on_delete=models.CASCADE) - can_clone_instances = models.BooleanField(default=True) - max_instances = models.IntegerField(default=1, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1),]) - max_cpus = models.IntegerField(default=1, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1)]) - max_memory = models.IntegerField(default=2048, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1)]) - max_disk_size = models.IntegerField(default=20, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1)]) + +class UserAttributes(Model): + user = OneToOneField(User, on_delete=CASCADE) + can_clone_instances = BooleanField(default=True) + max_instances = IntegerField(default=1, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1), ]) + max_cpus = IntegerField(default=1, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1)]) + max_memory = IntegerField(default=2048, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1)]) + max_disk_size = IntegerField(default=20, help_text="-1 for unlimited. Any integer value", validators=[MinValueValidator(-1)]) @staticmethod def create_missing_userattributes(user): diff --git a/accounts/templates/account.html b/accounts/templates/account.html index 56f91b8..0f9bbb7 100644 --- a/accounts/templates/account.html +++ b/accounts/templates/account.html @@ -87,8 +87,8 @@ <div class="form-group"> <label class="col-sm-4 control-label">{% trans "VNC" %}</label> <div class="col-sm-6"> - <select type="text" class="form-control" name="inst_vnc"> - <option value="">False</option> + <select class="form-control" name="inst_vnc"> + <option value="">{% trans 'False' %}</option> <option value="1" {% if inst.is_vnc %}selected{% endif %}>True</option> </select> </div> @@ -96,8 +96,8 @@ <div class="form-group"> <label class="col-sm-4 control-label">{% trans "Resize" %}</label> <div class="col-sm-6"> - <select type="text" class="form-control" name="inst_change"> - <option value="">False</option> + <select class="form-control" name="inst_change"> + <option value="">{% trans 'False' %}</option> <option value="1" {% if inst.is_change %}selected{% endif %}>True</option> </select> </div> @@ -105,8 +105,8 @@ <div class="form-group"> <label class="col-sm-4 control-label">{% trans "Delete" %}</label> <div class="col-sm-6"> - <select type="text" class="form-control" name="inst_delete"> - <option value="">False</option> + <select class="form-control" name="inst_delete"> + <option value="">{% trans 'False' %}</option> <option value="1" {% if inst.is_delete %}selected{% endif %}>True</option> </select> </div> @@ -124,7 +124,7 @@ <td style="width:5px;"> <form action="" method="post" role="form">{% csrf_token %} <input type="hidden" name="user_inst" value="{{ inst.id }}"> - <button type="submit" class="btn btn-xs btn-default" name="delete" tittle="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')"> + <button type="submit" class="btn btn-xs btn-default" name="delete" title="{% trans "Delete" %}" onclick="return confirm('{% trans "Are you sure?" %}')"> <span class="glyphicon glyphicon-trash" aria-hidden="true"></span> </button> </form> diff --git a/accounts/urls.py b/accounts/urls.py index c0ea4f1..6b49b70 100644 --- a/accounts/urls.py +++ b/accounts/urls.py @@ -1,10 +1,10 @@ -from django.conf.urls import url +from django.urls import path, re_path from django.contrib.auth import views as auth_views from . import views urlpatterns = [ - url(r'^login/$', auth_views.LoginView.as_view(template_name='login.html'), name='login'), - url(r'^logout/$', auth_views.LogoutView.as_view(template_name='logout.html'), name='logout'), - url(r'^profile/$', views.profile, name='profile'), url(r'^$', views.accounts, name='accounts'), - url(r'^profile/(?P<user_id>[0-9]+)/$', views.account, name='account'), + path('login/', auth_views.LoginView.as_view(template_name='login.html'), name='login'), + path('logout/', auth_views.LogoutView.as_view(template_name='logout.html'), name='logout'), + path('profile/', views.profile, name='profile'), path('', views.accounts, name='accounts'), + re_path(r'^profile/(?P<user_id>[0-9]+)/$', views.account, name='account'), ] diff --git a/computes/forms.py b/computes/forms.py index 5389708..bbde4d4 100644 --- a/computes/forms.py +++ b/computes/forms.py @@ -151,10 +151,8 @@ class ComputeEditHostForm(forms.Form): class ComputeAddSocketForm(forms.Form): - name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, - max_length=64) - details = forms.CharField(error_messages={'required': _('No details has been entred')}, - max_length=50) + name = forms.CharField(error_messages={'required': _('No hostname has been entered')}, max_length=64) + details = forms.CharField(error_messages={'required': _('No details has been entred')}, max_length=50) def clean_name(self): name = self.cleaned_data['name'] diff --git a/computes/migrations/0001_initial.py b/computes/migrations/0001_initial.py index e8d6139..c8f9183 100644 --- a/computes/migrations/0001_initial.py +++ b/computes/migrations/0001_initial.py @@ -1,11 +1,12 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals +# Generated by Django 2.2.10 on 2020-01-28 07:01 -from django.db import models, migrations +from django.db import migrations, models class Migration(migrations.Migration): + initial = True + dependencies = [ ] @@ -13,15 +14,13 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Compute', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=20)), - ('hostname', models.CharField(max_length=20)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=64)), + ('hostname', models.CharField(max_length=64)), ('login', models.CharField(max_length=20)), - ('password', models.CharField(max_length=14, null=True, blank=True)), + ('password', models.CharField(blank=True, max_length=14, null=True)), + ('details', models.CharField(blank=True, max_length=64, null=True)), ('type', models.IntegerField()), ], - options={ - }, - bases=(models.Model,), ), ] diff --git a/computes/migrations/0002_compute_details.py b/computes/migrations/0002_compute_details.py deleted file mode 100644 index 1e0fdf5..0000000 --- a/computes/migrations/0002_compute_details.py +++ /dev/null @@ -1,18 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - -class Migration(migrations.Migration): - - dependencies = [ - ('computes', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='Compute', - name='details', - field=models.CharField(max_length=50, null=True, blank=True), - ), - ] diff --git a/computes/migrations/0003_auto_20200121_1523.py b/computes/migrations/0003_auto_20200121_1523.py deleted file mode 100644 index 361cbc1..0000000 --- a/computes/migrations/0003_auto_20200121_1523.py +++ /dev/null @@ -1,30 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.26 on 2020-01-21 12:23 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('computes', '0002_compute_details'), - ] - - operations = [ - migrations.AlterField( - model_name='compute', - name='details', - field=models.CharField(blank=True, max_length=64, null=True), - ), - migrations.AlterField( - model_name='compute', - name='hostname', - field=models.CharField(max_length=64), - ), - migrations.AlterField( - model_name='compute', - name='name', - field=models.CharField(max_length=64), - ), - ] diff --git a/computes/models.py b/computes/models.py index 1a83e59..db224a3 100644 --- a/computes/models.py +++ b/computes/models.py @@ -1,13 +1,13 @@ -from django.db import models +from django.db.models import Model, CharField, IntegerField -class Compute(models.Model): - name = models.CharField(max_length=64) - hostname = models.CharField(max_length=64) - login = models.CharField(max_length=20) - password = models.CharField(max_length=14, blank=True, null=True) - details = models.CharField(max_length=64, null=True, blank=True) - type = models.IntegerField() +class Compute(Model): + name = CharField(max_length=64) + hostname = CharField(max_length=64) + login = CharField(max_length=20) + password = CharField(max_length=14, blank=True, null=True) + details = CharField(max_length=64, null=True, blank=True) + type = IntegerField() def __unicode__(self): return self.hostname diff --git a/computes/urls.py b/computes/urls.py index 350fc00..be5f09b 100644 --- a/computes/urls.py +++ b/computes/urls.py @@ -1,4 +1,4 @@ -from django.conf.urls import url +from django.urls import path, re_path from storages.views import storages, storage, get_volumes from networks.views import networks, network from secrets.views import secrets @@ -9,23 +9,24 @@ from instances.views import instances from nwfilters.views import nwfilter, nwfilters urlpatterns = [ - url(r'^$', computes, name='computes'), - url(r'^(?P<compute_id>[0-9]+)/$', overview, name='overview'), - url(r'^(?P<compute_id>[0-9]+)/statistics$', compute_graph, name='compute_graph'), - url(r'^(?P<compute_id>[0-9]+)/instances/$', instances, name='instances'), - url(r'^(?P<compute_id>[0-9]+)/storages/$', storages, name='storages'), - url(r'^(?P<compute_id>[0-9]+)/storage/(?P<pool>[\w\-\.\/]+)/volumes$', get_volumes, name='volumes'), - url(r'^(?P<compute_id>[0-9]+)/storage/(?P<pool>[\w\-\.\/]+)/$', storage, name='storage'), - url(r'^(?P<compute_id>[0-9]+)/networks/$', networks, name='networks'), - url(r'^(?P<compute_id>[0-9]+)/network/(?P<pool>[\w\-\.]+)/$', network, name='network'), - url(r'^(?P<compute_id>[0-9]+)/interfaces/$', interfaces, name='interfaces'), - url(r'^(?P<compute_id>[0-9]+)/interface/(?P<iface>[\w\-\.\:]+)/$', interface, name='interface'), - url(r'^(?P<compute_id>[0-9]+)/nwfilters/$', nwfilters, name='nwfilters'), - url(r'^(?P<compute_id>[0-9]+)/nwfilter/(?P<nwfltr>[\w\-\.\:]+)/$', nwfilter, name='nwfilter'), - url(r'^(?P<compute_id>[0-9]+)/secrets/$', secrets, name='secrets'), - url(r'^(?P<compute_id>[0-9]+)/create/$', create_instance_select_type, name='create_instance_select_type'), - url(r'^(?P<compute_id>[0-9]+)/create/archs/(?P<arch>[\w\-\.\/]+)/machines/(?P<machine>[\w\-\.\/]+)$', create_instance, name='create_instance'), - url(r'^(?P<compute_id>[0-9]+)/archs/(?P<arch>[\w\-\.\/]+)/machines$', get_compute_machine_types, name='machines'), - url(r'^(?P<compute_id>[0-9]+)/archs/(?P<arch>[\w\-\.\/]+)/machines/(?P<machine>[\w\-\.\/]+)/disks/(?P<disk>[\w\-\.\/]+)/buses$', get_compute_disk_buses, name='buses'), - url(r'^(?P<compute_id>[0-9]+)/archs/(?P<arch>[\w\-\.\/]+)/machines/(?P<machine>[\w\-\.\/]+)/capabilities$', get_dom_capabilities, name='domcaps'), + path('', computes, name='computes'), + re_path(r'^(?P<compute_id>[0-9]+)/$', overview, name='overview'), + re_path(r'^(?P<compute_id>[0-9]+)/statistics$', compute_graph, name='compute_graph'), + re_path(r'^(?P<compute_id>[0-9]+)/instances/$', instances, name='instances'), + re_path(r'^(?P<compute_id>[0-9]+)/storages/$', storages, name='storages'), + re_path(r'^(?P<compute_id>[0-9]+)/storage/(?P<pool>[\w\-\.\/]+)/volumes$', get_volumes, name='volumes'), + re_path(r'^(?P<compute_id>[0-9]+)/storage/(?P<pool>[\w\-\.\/]+)/$', storage, name='storage'), + re_path(r'^(?P<compute_id>[0-9]+)/networks/$', networks, name='networks'), + re_path(r'^(?P<compute_id>[0-9]+)/network/(?P<pool>[\w\-\.]+)/$', network, name='network'), + re_path(r'^(?P<compute_id>[0-9]+)/interfaces/$', interfaces, name='interfaces'), + re_path(r'^(?P<compute_id>[0-9]+)/interface/(?P<iface>[\w\-\.\:]+)/$', interface, name='interface'), + re_path(r'^(?P<compute_id>[0-9]+)/nwfilters/$', nwfilters, name='nwfilters'), + re_path(r'^(?P<compute_id>[0-9]+)/nwfilter/(?P<nwfltr>[\w\-\.\:]+)/$', nwfilter, name='nwfilter'), + re_path(r'^(?P<compute_id>[0-9]+)/secrets/$', secrets, name='secrets'), + re_path(r'^(?P<compute_id>[0-9]+)/create/$', create_instance_select_type, name='create_instance_select_type'), + re_path(r'^(?P<compute_id>[0-9]+)/create/archs/(?P<arch>[\w\-\.\/]+)/machines/(?P<machine>[\w\-\.\/]+)$', create_instance, name='create_instance'), + re_path(r'^(?P<compute_id>[0-9]+)/archs/(?P<arch>[\w\-\.\/]+)/machines$', get_compute_machine_types, name='machines'), + re_path(r'^(?P<compute_id>[0-9]+)/archs/(?P<arch>[\w\-\.\/]+)/machines/(?P<machine>[\w\-\.\/]+)/disks/(?P<disk>[\w\-\.\/]+)/buses$', get_compute_disk_buses, name='buses'), + re_path(r'^(?P<compute_id>[0-9]+)/archs/(?P<arch>[\w\-\.\/]+)/machines/(?P<machine>[\w\-\.\/]+)/capabilities$', get_dom_capabilities, name='domcaps'), ] + diff --git a/conf/daemon/gstfsd b/conf/daemon/gstfsd index 1851770..589cf8b 100644 --- a/conf/daemon/gstfsd +++ b/conf/daemon/gstfsd @@ -3,7 +3,7 @@ # gstfsd - WebVirtCloud daemon for managing VM's filesystem # -import SocketServer +import socketserver import json import guestfs import re @@ -13,11 +13,11 @@ PORT = 16510 ADDRESS = "0.0.0.0" -class MyTCPServer(SocketServer.ThreadingTCPServer): +class MyTCPServer(socketserver.ThreadingTCPServer): allow_reuse_address = True -class MyTCPServerHandler(SocketServer.BaseRequestHandler): +class MyTCPServerHandler(socketserver.BaseRequestHandler): def handle(self): # recive data data = json.loads(self.request.recv(1024).strip()) @@ -42,9 +42,9 @@ class MyTCPServerHandler(SocketServer.BaseRequestHandler): if data['action'] == 'publickey': if not gfs.is_dir('/root/.ssh'): gfs.mkdir('/root/.ssh') - gfs.chmod(0700, "/root/.ssh") + gfs.chmod(700, "/root/.ssh") gfs.write('/root/.ssh/authorized_keys', data['key']) - gfs.chmod(0600, '/root/.ssh/authorized_keys') + gfs.chmod(600, '/root/.ssh/authorized_keys') self.request.sendall(json.dumps({'return': 'success'})) gfs.umount(part) except RuntimeError: @@ -52,7 +52,7 @@ class MyTCPServerHandler(SocketServer.BaseRequestHandler): gfs.shutdown() gfs.close() except RuntimeError as err: - self.request.sendall(json.dumps({'return': 'error', 'message': err.message})) + self.request.sendall(json.dumps({'return': 'error', 'message': err})) server = MyTCPServer((ADDRESS, PORT), MyTCPServerHandler) diff --git a/conf/requirements.txt b/conf/requirements.txt index fc57c17..11adabb 100644 --- a/conf/requirements.txt +++ b/conf/requirements.txt @@ -1,7 +1,8 @@ -Django==1.11.26 +Django==2.2.10 websockify==0.9.0 -gunicorn==19.9.0 -lxml==4.4.2 -libvirt-python==5.10.0 +gunicorn==20.0.4 +lxml==4.5.0 +libvirt-python==6.1.0 +six pytz rwlock diff --git a/conf/runit/secret_generator.py b/conf/runit/secret_generator.py index 830ba9d..2a5a8dc 100644 --- a/conf/runit/secret_generator.py +++ b/conf/runit/secret_generator.py @@ -1,4 +1,4 @@ import random, string haystack = string.ascii_letters + string.digits + string.punctuation -print(''.join([random.SystemRandom().choice(haystack.replace('/','').replace('\'', '').replace('\"','')) for _ in range(50)])) \ No newline at end of file +print(''.join([random.SystemRandom().choice(haystack.replace('/', '').replace('\'', '').replace('\"', '')) for _ in range(50)])) diff --git a/conf/supervisor/gstfsd.conf b/conf/supervisor/gstfsd.conf index 2834b30..094f41c 100644 --- a/conf/supervisor/gstfsd.conf +++ b/conf/supervisor/gstfsd.conf @@ -1,5 +1,5 @@ [program:gstfsd] -command=/usr/bin/python /usr/local/bin/gstfsd +command=/srv/webvirtcloud/venv/bin/python3 /usr/local/bin/gstfsd directory=/usr/local/bin user=root autostart=true diff --git a/conf/supervisor/webvirtcloud.conf b/conf/supervisor/webvirtcloud.conf index 2994bc9..692fe8a 100644 --- a/conf/supervisor/webvirtcloud.conf +++ b/conf/supervisor/webvirtcloud.conf @@ -7,7 +7,7 @@ autorestart=true redirect_stderr=true [program:novncd] -command=/srv/webvirtcloud/venv/bin/python /srv/webvirtcloud/console/novncd +command=/srv/webvirtcloud/venv/bin/python3 /srv/webvirtcloud/console/novncd directory=/srv/webvirtcloud user=www-data autostart=true diff --git a/console/novncd b/console/novncd index 0f205a0..15ac905 100755 --- a/console/novncd +++ b/console/novncd @@ -7,7 +7,7 @@ import django DIR_PATH = os.path.dirname(os.path.abspath(__file__)) ROOT_PATH = os.path.abspath(os.path.join(DIR_PATH, '..', '')) -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webvirtcloud.settings") +os.environ["DJANGO_SETTINGS_MODULE"] = "webvirtcloud.settings" CERT = DIR_PATH + '/cert.pem' if ROOT_PATH not in sys.path: @@ -15,16 +15,16 @@ if ROOT_PATH not in sys.path: django.setup() -# VENV_PATH = ROOT_PATH + '/venv/lib/python2.7/site-packages' +# VENV_PATH = ROOT_PATH + '/venv/lib/python3.6/site-packages' # if VENV_PATH not in sys.path: # sys.path.append(VENV_PATH) import re -import Cookie import socket +from six.moves import http_cookies as Cookie from webvirtcloud.settings import WS_PORT, WS_HOST, WS_CERT from vrtManager.connection import CONN_SSH, CONN_SOCKET -from tunnel import Tunnel +from console.tunnel import Tunnel from optparse import OptionParser parser = OptionParser() @@ -127,12 +127,30 @@ def get_connection_infos(token): class CompatibilityMixIn(object): def _new_client(self, daemon, socket_factory): - cookie = Cookie.SimpleCookie() - cookie.load(self.headers.getheader('cookie')) - if 'token' not in cookie: - self.msg('No token cookie found !') - return False - token = cookie['token'].value + # NoVNC uses it's own convention that forward token + # from the request to a cookie header, we should check + # also for this behavior + hcookie = self.headers.get('cookie') + if hcookie: + cookie = Cookie.SimpleCookie() + for hcookie_part in hcookie.split(';'): + hcookie_part = hcookie_part.lstrip() + try: + cookie.load(hcookie_part) + except Cookie.CookieError: + # NOTE(stgleb): Do not print out cookie content + # for security reasons. + self.msg('Found malformed cookie') + else: + if 'token' in cookie: + token = cookie['token'].value + + # cookie = Cookie.SimpleCookie() + # cookie.load(self.headers.getheader('cookie')) + # if 'token' not in cookie: + # self.msg('No token cookie found !') + # return False + # token = cookie['token'].value (connhost, connport, connuser, conntype, console_host, console_port, console_socket) = get_connection_infos(token) diff --git a/console/templates/console-base.html b/console/templates/console-base.html index e5c7ffe..5a79a01 100644 --- a/console/templates/console-base.html +++ b/console/templates/console-base.html @@ -35,7 +35,6 @@ margin-left: auto; margin-right: auto; display: block; - margin: auto; } #status { diff --git a/console/templates/console-spice-full.html b/console/templates/console-spice-full.html index 08ef3ee..aac780d 100644 --- a/console/templates/console-spice-full.html +++ b/console/templates/console-spice-full.html @@ -25,65 +25,28 @@ {% extends "console-base.html" %} {% load i18n %} {% load staticfiles %} + {% block head %} <title>WebVirtCloud - Spice Client - Full</title> - <script src="{% static "js/spice-html5/spicearraybuffer.js" %}"></script> - <script src="{% static "js/spice-html5/enums.js" %}"></script> - <script src="{% static "js/spice-html5/atKeynames.js" %}"></script> - <script src="{% static "js/spice-html5/utils.js" %}"></script> - <script src="{% static "js/spice-html5/png.js" %}"></script> - <script src="{% static "js/spice-html5/lz.js" %}"></script> - <script src="{% static "js/spice-html5/quic.js" %}"></script> - <script src="{% static "js/spice-html5/bitmap.js" %}"></script> - <script src="{% static "js/spice-html5/spicedataview.js" %}"></script> - <script src="{% static "js/spice-html5/spicetype.js" %}"></script> - <script src="{% static "js/spice-html5/spicemsg.js" %}"></script> - <script src="{% static "js/spice-html5/wire.js" %}"></script> - <script src="{% static "js/spice-html5/spiceconn.js" %}"></script> - <script src="{% static "js/spice-html5/display.js" %}"></script> - <script src="{% static "js/spice-html5/port.js" %}"></script> - <script src="{% static "js/spice-html5/main.js" %}"></script> - <script src="{% static "js/spice-html5/inputs.js" %}"></script> - <script src="{% static "js/spice-html5/webm.js" %}"></script> - <script src="{% static "js/spice-html5/playback.js" %}"></script> - <script src="{% static "js/spice-html5/simulatecursor.js" %}"></script> - <script src="{% static "js/spice-html5/cursor.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/jsbn.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/rsa.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/prng4.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/rng.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/sha1.js" %}"></script> - <script src="{% static "js/spice-html5/ticket.js" %}"></script> - <script src="{% static "js/spice-html5/resize.js" %}"></script> - <script src="{% static "js/spice-html5/filexfer.js" %}"></script> <link rel="stylesheet" type="text/css" href="{% static "js/spice-html5/spice.css" %}" /> -{% endblock %} - -{% block content %} - - <div id="login" hidden> - <span class="logo">SPICE</span> - <label for="host">{% trans 'Host' %}:</label> <input type='text' id='host' value='{{ ws_host }}'> <!-- localhost --> - <label for="port">{% trans 'Port' %}:</label> <input type='text' id='port' value='{{ ws_port }}'> - <label for="password">{% trans 'Password' %}:</label> <input type='password' id='password' value='{{ console_passwd }}'> - <label for="show_console">{% trans 'Show console' %}</label><input type="checkbox" id="show_console" value="1" onchange="toggle_console()" checked> - <button id="connectButton" onclick="connect();">{% trans 'Start' %}</button> - </div> - - <div id="spice-area"> - <div id="spice-screen" class="spice-screen"></div> - <div id="message-div" class="spice-message"></div> - </div> - - <div id="debug-div"> - <!-- If DUMPXXX is turned on, dumped images will go here --> - </div> - -{% endblock %} - -{% block foot %} + <!-- ES2015/ES6 modules polyfill --> + <script type="module"> + window._spice_has_module_support = true; + </script> <script> + window.addEventListener("load", function() { + if (window._spice_has_module_support) return; + var loader = document.createElement("script"); + loader.src = '{% static "thirdparty/browser-es-module-loader/dist/browser-es-module-loader.js" %}'; + document.head.appendChild(loader); + }); + </script> + + <script type="module" crossorigin="anonymous"> + + import * as SpiceHtml5 from '{% static "js/spice-html5/main.js" %}'; + var host = null, port = null; var sc; @@ -96,9 +59,6 @@ host = document.getElementById("host").value; port = document.getElementById("port").value; - if (window.location.protocol == 'https:') { - scheme = "wss://"; - } password = document.getElementById("password").value; if ((!host) || (!port)) { @@ -116,11 +76,10 @@ document.getElementById('connectButton').onclick = disconnect; try { - sc = new SpiceMainConn({uri: uri, screen_id: "spice-screen", dump_id: "debug-div", + sc = new SpiceHtml5.SpiceMainConn({uri: uri, screen_id: "spice-screen", dump_id: "debug-div", message_id: "message-div", password: password, onerror: spice_error, onagent: agent_connected }); } - catch (e) - { + catch (e) { alert(e.toString()); disconnect(); } @@ -135,25 +94,27 @@ document.getElementById('connectButton').onclick = connect; if (window.File && window.FileReader && window.FileList && window.Blob) { var spice_xfer_area = document.getElementById('spice-xfer-area'); - document.getElementById('spice-area').removeChild(spice_xfer_area); - document.getElementById('spice-area').removeEventListener('dragover', handle_file_dragover, false); - document.getElementById('spice-area').removeEventListener('drop', handle_file_drop, false); + if (spice_xfer_area != null) { + document.getElementById('spice-area').removeChild(spice_xfer_area); + } + document.getElementById('spice-area').removeEventListener('dragover', SpiceHtml5.handle_file_dragover, false); + document.getElementById('spice-area').removeEventListener('drop', SpiceHtml5.handle_file_drop, false); } console.log("<< disconnect"); } function agent_connected(sc) { - window.addEventListener('resize', handle_resize); + window.addEventListener('resize', SpiceHtml5.handle_resize); window.spice_connection = this; - resize_helper(this); + SpiceHtml5.resize_helper(this); if (window.File && window.FileReader && window.FileList && window.Blob) { var spice_xfer_area = document.createElement("div"); spice_xfer_area.setAttribute('id', 'spice-xfer-area'); document.getElementById('spice-area').appendChild(spice_xfer_area); - document.getElementById('spice-area').addEventListener('dragover', handle_file_dragover, false); - document.getElementById('spice-area').addEventListener('drop', handle_file_drop, false); + document.getElementById('spice-area').addEventListener('dragover', SpiceHtml5.handle_file_dragover, false); + document.getElementById('spice-area').addEventListener('drop', SpiceHtml5.handle_file_drop, false); } else { console.log("File API is not supported"); @@ -171,20 +132,9 @@ m.style.display = 'none'; } - window.addEventListener('resize', handle_resize); - resize_helper(sc); - } - - function fullscreen() { - var screen=document.getElementById('spice-screen'); - if(screen.requestFullscreen) { - screen.requestFullscreen(); - } else if(screen.mozRequestFullScreen) { - screen.mozRequestFullScreen(); - } else if(screen.webkitRequestFullscreen) { - screen.webkitRequestFullscreen(); - } else if(screen.msRequestFullscreen) { - screen.msRequestFullscreen(); + window.addEventListener('resize', SpiceHtml5.handle_resize); + if (sc) { + SpiceHtml5.resize_helper(sc); } } /* SPICE port event listeners @@ -198,20 +148,72 @@ DEBUG > 0 && console.log('SPICE port', event.detail.channel.portName, 'event data:', event.detail.spiceEvent); }); */ - document.getElementById("fullscreen_button").addEventListener('click', fullscreen); - document.getElementById('ctrlaltdel').addEventListener('click', sendCtrlAltDel); - document.getElementById('ctrlaltf1').addEventListener('click', function(){sendCtrlAltFN(0);}); - document.getElementById('ctrlaltf2').addEventListener('click', function(){sendCtrlAltFN(1);}); - document.getElementById('ctrlaltf3').addEventListener('click', function(){sendCtrlAltFN(2);}); - document.getElementById('ctrlaltf4').addEventListener('click', function(){sendCtrlAltFN(3);}); - document.getElementById('ctrlaltf5').addEventListener('click', function(){sendCtrlAltFN(4);}); - document.getElementById('ctrlaltf6').addEventListener('click', function(){sendCtrlAltFN(5);}); - document.getElementById('ctrlaltf7').addEventListener('click', function(){sendCtrlAltFN(6);}); - document.getElementById('ctrlaltf8').addEventListener('click', function(){sendCtrlAltFN(7);}); - document.getElementById('ctrlaltf9').addEventListener('click', function(){sendCtrlAltFN(8);}); - document.getElementById('ctrlaltf10').addEventListener('click', function(){sendCtrlAltFN(9);}); - document.getElementById('ctrlaltf11').addEventListener('click', function(){sendCtrlAltFN(10);}); - document.getElementById('ctrlaltf12').addEventListener('click', function(){sendCtrlAltFN(11);}); - connect(); - </script> + + function fullscreen() { + var screen=document.getElementById('spice-screen'); + if(screen.requestFullscreen) { + screen.requestFullscreen(); + } else if(screen.mozRequestFullScreen) { + screen.mozRequestFullScreen(); + } else if(screen.webkitRequestFullscreen) { + screen.webkitRequestFullscreen(); + } else if(screen.msRequestFullscreen) { + screen.msRequestFullscreen(); + } + } + /* SPICE port event listeners + window.addEventListener('spice-port-data', function(event) { + // Here we convert data to text, but really we can obtain binary data also + var msg_text = arraybuffer_to_str(new Uint8Array(event.detail.data)); + DEBUG > 0 && console.log('SPICE port', event.detail.channel.portName, 'message text:', msg_text); + }); + + window.addEventListener('spice-port-event', function(event) { + DEBUG > 0 && console.log('SPICE port', event.detail.channel.portName, 'event data:', event.detail.spiceEvent); + }); + */ + document.getElementById("fullscreen_button").addEventListener('click', fullscreen); + document.getElementById('ctrlaltdel').addEventListener('click', function(){sendCtrlAltDel(sc);}); + document.getElementById('ctrlaltf1').addEventListener('click', function(){sendCtrlAltFN(0);}); + document.getElementById('ctrlaltf2').addEventListener('click', function(){sendCtrlAltFN(1);}); + document.getElementById('ctrlaltf3').addEventListener('click', function(){sendCtrlAltFN(2);}); + document.getElementById('ctrlaltf4').addEventListener('click', function(){sendCtrlAltFN(3);}); + document.getElementById('ctrlaltf5').addEventListener('click', function(){sendCtrlAltFN(4);}); + document.getElementById('ctrlaltf6').addEventListener('click', function(){sendCtrlAltFN(5);}); + document.getElementById('ctrlaltf7').addEventListener('click', function(){sendCtrlAltFN(6);}); + document.getElementById('ctrlaltf8').addEventListener('click', function(){sendCtrlAltFN(7);}); + document.getElementById('ctrlaltf9').addEventListener('click', function(){sendCtrlAltFN(8);}); + document.getElementById('ctrlaltf10').addEventListener('click', function(){sendCtrlAltFN(9);}); + document.getElementById('ctrlaltf11').addEventListener('click', function(){sendCtrlAltFN(10);}); + document.getElementById('ctrlaltf12').addEventListener('click', function(){sendCtrlAltFN(11);}); + + document.getElementById('connectButton').onclick = connect; + document.getElementById('show_console').onchange = toggle_console; +</script> +{% endblock %} + +{% block content %} + <div id="login"> + <span class="logo">SPICE</span> + <label for="host">{% trans 'Host' %}:</label> <input type='text' id='host' value='{{ ws_host }}'> <!-- localhost --> + <label for="port">{% trans 'Port' %}:</label> <input type='text' id='port' value='{{ ws_port }}'> + <label for="password">{% trans 'Password' %}:</label> <input type='password' id='password' value='{{ console_passwd }}'> + <label for="show_console">{% trans 'Show console' %}</label><input type="checkbox" id="show_console" value="1" onchange="toggle_console()" checked> + <button id="connectButton">{% trans 'Start' %}</button> + </div> + + <div id="spice-area"> + <div id="spice-screen" class="spice-screen"></div> + </div> + + <div id="message-div" class="spice-message"></div> + + <div id="debug-div"> + <!-- If DUMPXXX is turned on, dumped images will go here --> + </div> + +{% endblock %} + +{% block foot %} + {% endblock %} diff --git a/console/templates/console-spice-lite.html b/console/templates/console-spice-lite.html index f1e272c..d498f0f 100644 --- a/console/templates/console-spice-lite.html +++ b/console/templates/console-spice-lite.html @@ -25,56 +25,27 @@ {% extends "console-base.html" %} {% load i18n %} {% load staticfiles %} + {% block head %} - <title>WebVirtCloud - Spice - Lite</title> - <script src="{% static "js/spice-html5/spicearraybuffer.js" %}"></script> - <script src="{% static "js/spice-html5/enums.js" %}"></script> - <script src="{% static "js/spice-html5/atKeynames.js" %}"></script> - <script src="{% static "js/spice-html5/utils.js" %}"></script> - <script src="{% static "js/spice-html5/png.js" %}"></script> - <script src="{% static "js/spice-html5/lz.js" %}"></script> - <script src="{% static "js/spice-html5/quic.js" %}"></script> - <script src="{% static "js/spice-html5/bitmap.js" %}"></script> - <script src="{% static "js/spice-html5/spicedataview.js" %}"></script> - <script src="{% static "js/spice-html5/spicetype.js" %}"></script> - <script src="{% static "js/spice-html5/spicemsg.js" %}"></script> - <script src="{% static "js/spice-html5/wire.js" %}"></script> - <script src="{% static "js/spice-html5/spiceconn.js" %}"></script> - <script src="{% static "js/spice-html5/display.js" %}"></script> - <script src="{% static "js/spice-html5/main.js" %}"></script> - <script src="{% static "js/spice-html5/inputs.js" %}"></script> - <script src="{% static "js/spice-html5/webm.js" %}"></script> - <script src="{% static "js/spice-html5/playback.js" %}"></script> - <script src="{% static "js/spice-html5/simulatecursor.js" %}"></script> - <script src="{% static "js/spice-html5/cursor.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/jsbn.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/rsa.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/prng4.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/rng.js" %}"></script> - <script src="{% static "js/spice-html5/thirdparty/sha1.js" %}"></script> - <script src="{% static "js/spice-html5/ticket.js" %}"></script> - <script src="{% static "js/spice-html5/resize.js" %}"></script> - <script src="{% static "js/spice-html5/filexfer.js" %}"></script> - <script src="{% static "js/spice-html5/port.js" %}"></script> - <link rel="stylesheet" type="text/css" href="{% static "js/spice-html5/spice.css" %}" /> -{% endblock %} - -{% block content %} - <div id="spice-area"> - <div id="spice-screen" class="spice-screen"></div> - <div id="message-div" class="spice-message"></div> - </div> - - <div id="debug-div"> - <!-- If DUMPXXX is turned on, dumped images will go here --> - </div> -{% endblock %} - -{% block foot %} + <!-- ES2015/ES6 modules polyfill --> + <script type="module"> + window._spice_has_module_support = true; + </script> <script> + window.addEventListener("load", function() { + if (window._spice_has_module_support) return; + var loader = document.createElement("script"); + loader.src = '{% static "thirdparty/browser-es-module-loader/dist/browser-es-module-loader.js" %}'; + document.head.appendChild(loader); + }); + </script> + + <script type="module" crossorigin="anonymous"> + import * as SpiceHtml5 from '{% static "js/spice-html5/main.js" %}'; + var host = null, port = null; var sc; @@ -92,21 +63,18 @@ } function spice_error(e) { - console.log(e); disconnect(); - if (e.message !== undefined) { - log_error(e.message); - } - else { - log_error('Unknown error'); + if (e !== undefined && e.message === "Permission denied.") { + var pass = prompt("Password"); + connect(pass); } } - function connect() { - var host, port, password, scheme = "ws://", uri; - console.log('>> connect'); + function connect(password) { + var host, port, scheme = "ws://", uri; + // By default, use the host and port of server that served this file - //host = spice_query_var('host', window.location.hostname); + // host = spice_query_var('host', window.location.hostname); host = '{{ ws_host| safe }}'; // Note that using the web server port only makes sense @@ -129,16 +97,18 @@ // If a token variable is passed in, set the parameter in a cookie. // This is used by nova-spiceproxy. - token = spice_query_var('token', null); + var token = spice_query_var('token', null); if (token) { spice_set_cookie('token', token, 1) } - //password = spice_query_var('password', ''); - password = '{{ console_passwd | safe }}'; + if (password === undefined) { + password = spice_query_var('password', ''); + password = '{{ console_passwd | safe }}'; + } if (password === 'None') password = ''; - path = spice_query_var('path', 'websockify'); + var path = spice_query_var('path', 'websockify'); if ((!host) || (!port)) { console.log("must specify host and port in URL"); @@ -156,43 +126,44 @@ } try { - sc = new SpiceMainConn({uri: uri, screen_id: "spice-screen", dump_id: "debug-div", + sc = new SpiceHtml5.SpiceMainConn({uri: uri, screen_id: "spice-screen", dump_id: "debug-div", message_id: "message-div", password: password, onerror: spice_error, onagent: agent_connected }); } catch (e) { alert(e.toString()); disconnect(); } - console.log('<< connect') + } - function disconnect() - { + function disconnect() { console.log(">> disconnect"); if (sc) { sc.stop(); } if (window.File && window.FileReader && window.FileList && window.Blob) { var spice_xfer_area = document.getElementById('spice-xfer-area'); - document.getElementById('spice-area').removeChild(spice_xfer_area); - document.getElementById('spice-area').removeEventListener('dragover', handle_file_dragover, false); - document.getElementById('spice-area').removeEventListener('drop', handle_file_drop, false); + if (spice_xfer_area != null) { + document.getElementById('spice-area').removeChild(spice_xfer_area); + } + document.getElementById('spice-area').removeEventListener('dragover', SpiceHtml5.handle_file_dragover, false); + document.getElementById('spice-area').removeEventListener('drop', SpiceHtml5.handle_file_drop, false); } console.log("<< disconnect"); } function agent_connected(sc) { - window.addEventListener('resize', handle_resize); + window.addEventListener('resize', SpiceHtml5.handle_resize); window.spice_connection = this; - resize_helper(this); + SpiceHtml5.resize_helper(this); if (window.File && window.FileReader && window.FileList && window.Blob) { var spice_xfer_area = document.createElement("div"); spice_xfer_area.setAttribute('id', 'spice-xfer-area'); document.getElementById('spice-area').appendChild(spice_xfer_area); - document.getElementById('spice-area').addEventListener('dragover', handle_file_dragover, false); - document.getElementById('spice-area').addEventListener('drop', handle_file_drop, false); + document.getElementById('spice-area').addEventListener('dragover', SpiceHtml5.handle_file_dragover, false); + document.getElementById('spice-area').addEventListener('drop', SpiceHtml5.handle_file_drop, false); } else { console.log("File API is not supported"); @@ -224,7 +195,7 @@ }); */ document.getElementById("fullscreen_button").addEventListener('click', fullscreen); - document.getElementById('ctrlaltdel').addEventListener('click', sendCtrlAltDel); + document.getElementById('ctrlaltdel').addEventListener('click', function(){sendCtrlAltDel(sc);}); document.getElementById('ctrlaltf1').addEventListener('click', function(){sendCtrlAltFN(0);}); document.getElementById('ctrlaltf2').addEventListener('click', function(){sendCtrlAltFN(1);}); document.getElementById('ctrlaltf3').addEventListener('click', function(){sendCtrlAltFN(2);}); @@ -237,6 +208,22 @@ document.getElementById('ctrlaltf10').addEventListener('click', function(){sendCtrlAltFN(9);}); document.getElementById('ctrlaltf11').addEventListener('click', function(){sendCtrlAltFN(10);}); document.getElementById('ctrlaltf12').addEventListener('click', function(){sendCtrlAltFN(11);}); - connect(); + connect(undefined); </script> {% endblock %} +{% block content %} + <div id="login"> + <span class="logo">SPICE</span> + </div> + + <div id="spice-area"> + <div id="spice-screen" class="spice-screen"></div> + </div> + + <div id="message-div" class="spice-message"></div> + + <div id="debug-div"> + <!-- If DUMPXXX is turned on, dumped images will go here --> + </div> +{% endblock %} + diff --git a/console/tunnel.py b/console/tunnel.py index a6ba2c8..c7c19d6 100644 --- a/console/tunnel.py +++ b/console/tunnel.py @@ -27,6 +27,7 @@ import os import socket import signal import logging +from functools import reduce class Tunnel(object): @@ -103,7 +104,7 @@ class Tunnel(object): logging.debug("Tunnel PID=%d OUTFD=%d ERRFD=%d", pid, fds[0].fileno(), errorfds[0].fileno()) - errorfds[0].setblocking(0) + errorfds[0].setblocking(False) self.outfd = fds[0] self.errfd = errorfds[0] diff --git a/console/views.py b/console/views.py index 85b0a27..a27a562 100644 --- a/console/views.py +++ b/console/views.py @@ -33,7 +33,7 @@ def console(request): console_type = conn.get_console_type() console_websocket_port = conn.get_console_websocket_port() console_passwd = conn.get_console_passwd() - except libvirtError as lib_err: + except libvirtError: console_type = None console_websocket_port = None console_passwd = None diff --git a/create/forms.py b/create/forms.py index a869ca4..21695e2 100644 --- a/create/forms.py +++ b/create/forms.py @@ -62,4 +62,3 @@ class NewVMForm(forms.Form): elif len(name) > 64: raise forms.ValidationError(_('The name of the virtual machine must not exceed 20 characters')) return name - diff --git a/create/migrations/0001_initial.py b/create/migrations/0001_initial.py index 030ee30..102bc96 100644 --- a/create/migrations/0001_initial.py +++ b/create/migrations/0001_initial.py @@ -1,11 +1,12 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals +# Generated by Django 2.2.10 on 2020-01-28 07:01 -from django.db import models, migrations +from django.db import migrations, models class Migration(migrations.Migration): + initial = True + dependencies = [ ] @@ -13,14 +14,11 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Flavor', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), ('label', models.CharField(max_length=12)), ('memory', models.IntegerField()), ('vcpu', models.IntegerField()), ('disk', models.IntegerField()), ], - options={ - }, - bases=(models.Model,), ), ] diff --git a/create/migrations/0002_auto_20150325_0921.py b/create/migrations/0002_addFlavors.py similarity index 92% rename from create/migrations/0002_auto_20150325_0921.py rename to create/migrations/0002_addFlavors.py index 5594060..f3ea4b3 100644 --- a/create/migrations/0002_auto_20150325_0921.py +++ b/create/migrations/0002_addFlavors.py @@ -1,5 +1,4 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals +# Generated by Django 2.2.10 on 2020-01-28 07:01 from django.db import migrations @@ -28,4 +27,4 @@ class Migration(migrations.Migration): operations = [ migrations.RunPython(add_favors), - ] + ] \ No newline at end of file diff --git a/create/models.py b/create/models.py index 0572fdd..80bf9f3 100644 --- a/create/models.py +++ b/create/models.py @@ -1,11 +1,11 @@ -from django.db import models +from django.db.models import Model, CharField, IntegerField -class Flavor(models.Model): - label = models.CharField(max_length=12) - memory = models.IntegerField() - vcpu = models.IntegerField() - disk = models.IntegerField() +class Flavor(Model): + label = CharField(max_length=12) + memory = IntegerField() + vcpu = IntegerField() + disk = IntegerField() def __unicode__(self): return self.name diff --git a/create/templates/create_instance_w1.html b/create/templates/create_instance_w1.html index e4a5f2c..a75a0b2 100644 --- a/create/templates/create_instance_w1.html +++ b/create/templates/create_instance_w1.html @@ -94,7 +94,7 @@ </button> </form> </div> - <div class="clearfix"/> + <div class="clearfix"></div> </div> </div> </div> diff --git a/create/templates/create_instance_w2.html b/create/templates/create_instance_w2.html index 09a9484..9e00d7c 100644 --- a/create/templates/create_instance_w2.html +++ b/create/templates/create_instance_w2.html @@ -120,7 +120,7 @@ <div class="col-sm-6"> <select class="form-control" id="select_firmware" name="firmware"> {% for frm in firmwares %} - <option value="{{ frm }}" {% if frm == default_firmware %}selected{% endif %}>{{ frm }}</option> + <option value="{{ frm }}" {% if frm in default_firmware %}selected{% endif %}>{{ frm }}</option> {% endfor %} </select> </div> @@ -792,7 +792,7 @@ $.each(input_value.split(','), function (index, value) { let li = '<li>eth' + counter + ' -> ' + value + ' ' + - '<a class="btn-link pull-right" onclick="javascript:$(\'#network-control\').multiselect(\'deselect\', \'' + value + '\', true)"><i class="fa fa-remove"></i></a></a></li>'; + '<a class="btn-link pull-right" onclick="$(\'#network-control\').multiselect(\'deselect\', \'' + value + '\', true)"><i class="fa fa-remove"></i></a></a></li>'; selected_list_html += li; counter++; }); diff --git a/create/views.py b/create/views.py index c66484f..e2e81fb 100644 --- a/create/views.py +++ b/create/views.py @@ -19,9 +19,13 @@ from webvirtcloud.settings import QEMU_CONSOLE_DEFAULT_TYPE from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_IO from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_DETECT_ZEROES from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_DISCARD +from webvirtcloud.settings import INSTANCE_ARCH_DEFAULT_TYPE +from webvirtcloud.settings import INSTANCE_FIRMWARE_DEFAULT_TYPE + from django.contrib import messages from logs.views import addlogmsg + @login_required def create_instance_select_type(request, compute_id): @@ -45,8 +49,9 @@ def create_instance_select_type(request, compute_id): all_hypervisors = conn.get_hypervisors_machines() # Supported hypervisors by webvirtcloud: i686, x86_64(for now) supported_arch = ["x86_64", "i686", "aarch64", "armv7l", "ppc64", "ppc64le", "s390x"] - hypervisors = [hpv for hpv in all_hypervisors.keys() if hpv in supported_arch ] + hypervisors = [hpv for hpv in all_hypervisors.keys() if hpv in supported_arch] default_machine = INSTANCE_MACHINE_DEFAULT_TYPE + default_arch = INSTANCE_ARCH_DEFAULT_TYPE if request.method == 'POST': if 'create_xml' in request.POST: @@ -63,18 +68,21 @@ def create_instance_select_type(request, compute_id): conn._defineXML(xml) return HttpResponseRedirect(reverse('instance', args=[compute_id, name])) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) except libvirtError as lib_err: error_messages.append(lib_err) return render(request, 'create_instance_w1.html', locals()) + @login_required def create_instance(request, compute_id, arch, machine): """ :param request: :param compute_id: + :param arch: + :param machine: :return: """ if not request.user.is_superuser: @@ -96,6 +104,7 @@ def create_instance(request, compute_id, arch, machine): compute.password, compute.type) + default_firmware = INSTANCE_FIRMWARE_DEFAULT_TYPE default_cpu_mode = INSTANCE_CPU_DEFAULT_MODE instances = conn.get_instances() videos = conn.get_video_models(arch, machine) @@ -189,7 +198,7 @@ def create_instance(request, compute_id, arch, machine): volume_list.append(volume) is_disk_created = True except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) elif data['template']: templ_path = conn.get_volume_path(data['template']) dest_vol = conn.get_volume_path(data["name"] + ".img", data['storage']) @@ -221,7 +230,7 @@ def create_instance(request, compute_id, arch, machine): volume['bus'] = request.POST.get('bus' + str(idx), '') volume_list.append(volume) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if data['cache_mode'] not in conn.get_cache_modes(): error_msg = _("Invalid cache mode") error_messages.append(error_msg) diff --git a/dev/requirements.txt b/dev/requirements.txt index e88d0b2..d56ba0a 100644 --- a/dev/requirements.txt +++ b/dev/requirements.txt @@ -1,4 +1,4 @@ -r ../conf/requirements.txt -pep8==1.7.1 +pycodestyle pyflakes==2.1.1 -pylint==1.9.4 +pylint==2.4.4 diff --git a/gunicorn.conf.py b/gunicorn.conf.py index 8c07259..90bd54e 100644 --- a/gunicorn.conf.py +++ b/gunicorn.conf.py @@ -20,7 +20,7 @@ import os # range. # -#bind = 'unix:/srv/webvirtcloud/venv/wvcloud.socket' +# bind = 'unix:/srv/webvirtcloud/venv/wvcloud.socket' bind = '127.0.0.1:8000' backlog = 2048 diff --git a/instances/migrations/0001_initial.py b/instances/migrations/0001_initial.py index fe3c00f..e27f7aa 100644 --- a/instances/migrations/0001_initial.py +++ b/instances/migrations/0001_initial.py @@ -1,11 +1,13 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals +# Generated by Django 2.2.10 on 2020-01-28 07:01 -from django.db import models, migrations +from django.db import migrations, models +import django.db.models.deletion class Migration(migrations.Migration): + initial = True + dependencies = [ ('computes', '0001_initial'), ] @@ -14,13 +16,12 @@ class Migration(migrations.Migration): migrations.CreateModel( name='Instance', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), - ('name', models.CharField(max_length=20)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=120)), ('uuid', models.CharField(max_length=36)), - ('compute', models.ForeignKey(to='computes.Compute')), + ('is_template', models.BooleanField(default=False)), + ('created', models.DateField(auto_now_add=True)), + ('compute', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='computes.Compute')), ], - options={ - }, - bases=(models.Model,), ), ] diff --git a/instances/migrations/0002_instance_is_template.py b/instances/migrations/0002_instance_is_template.py deleted file mode 100644 index cbf2cdd..0000000 --- a/instances/migrations/0002_instance_is_template.py +++ /dev/null @@ -1,19 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('instances', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='instance', - name='is_template', - field=models.BooleanField(default=False), - ), - ] diff --git a/instances/migrations/0003_instance_created.py b/instances/migrations/0003_instance_created.py deleted file mode 100644 index 32d4ac9..0000000 --- a/instances/migrations/0003_instance_created.py +++ /dev/null @@ -1,21 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import migrations, models -import datetime - - -class Migration(migrations.Migration): - - dependencies = [ - ('instances', '0002_instance_is_template'), - ] - - operations = [ - migrations.AddField( - model_name='instance', - name='created', - field=models.DateField(default=datetime.datetime(2017, 10, 26, 8, 5, 55, 797326), auto_now_add=True), - preserve_default=False, - ), - ] diff --git a/instances/migrations/0004_auto_20180724_1136.py b/instances/migrations/0004_auto_20180724_1136.py deleted file mode 100644 index 82480cd..0000000 --- a/instances/migrations/0004_auto_20180724_1136.py +++ /dev/null @@ -1,20 +0,0 @@ -# -*- coding: utf-8 -*- -# Generated by Django 1.11.13 on 2018-07-24 11:36 -from __future__ import unicode_literals - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('instances', '0003_instance_created'), - ] - - operations = [ - migrations.AlterField( - model_name='instance', - name='name', - field=models.CharField(max_length=120), - ), - ] diff --git a/instances/models.py b/instances/models.py index b11c860..436ab41 100644 --- a/instances/models.py +++ b/instances/models.py @@ -1,13 +1,13 @@ -from django.db import models +from django.db.models import Model, ForeignKey, CharField, BooleanField, DateField, CASCADE from computes.models import Compute -class Instance(models.Model): - compute = models.ForeignKey(Compute, on_delete=models.CASCADE) - name = models.CharField(max_length=120) - uuid = models.CharField(max_length=36) - is_template = models.BooleanField(default=False) - created = models.DateField(auto_now_add=True) +class Instance(Model): + compute = ForeignKey(Compute, on_delete=CASCADE) + name = CharField(max_length=120) + uuid = CharField(max_length=36) + is_template = BooleanField(default=False) + created = DateField(auto_now_add=True) def __unicode__(self): return self.name diff --git a/instances/templates/edit_instance_volume.html b/instances/templates/edit_instance_volume.html index e0b5fd9..5b023e5 100644 --- a/instances/templates/edit_instance_volume.html +++ b/instances/templates/edit_instance_volume.html @@ -48,7 +48,7 @@ <div class="form-group"> <label class="col-sm-4 control-label">{% trans 'Bus' %}</label> <div class="col-sm-8"> - <select class="form-control" name="vol_bus"> + <select class="form-control" name="vol_bus" {% if status != 5 %} disabled {% endif %}> {% for bus in bus_host %} <option value="{{ bus }}" {% if bus == disk.bus %}selected{% endif %}>{{ bus }}</option> {% endfor %} @@ -110,6 +110,7 @@ </select> </div> </div> + <input class="form-control" name="vol_bus_old" value="{{ disk.bus }}"/> </div><!-- /.tabpane-content --> </div><!-- /.tab-content --> </div> <!-- /.modal-body --> diff --git a/instances/templates/instance.html b/instances/templates/instance.html index c3cb9c6..c3307c1 100644 --- a/instances/templates/instance.html +++ b/instances/templates/instance.html @@ -510,7 +510,7 @@ <div role="tabpanel" class="tab-pane tab-pane-bordered" id="resizevm_disk"> {% if request.user.is_superuser or request.user.is_staff or userinstance.is_change %} <form class="form-horizontal" method="post" role="form">{% csrf_token %} - <p style="font-weight:bold;">{% trans "Disk allocation (B):" %}</p> + <p style="font-weight:bold;">{% trans "Disk allocation (GB):" %}</p> {% for disk in disks %} <div class="form-group"> <label class="col-sm-4 control-label" style="font-weight:normal;">{% trans "Current allocation" %} ({{ disk.dev }})</label> @@ -704,25 +704,25 @@ </div> </form> <p style="font-weight:bold;">{% trans 'Boot Order' %}</p> - <form class="form-horizontal" action="" method="post" role="form">{% csrf_token %} - <div class="form-group"> - <div class="col-sm-12 col-sm-offset-2"> - {% ifequal status 5 %} - <p>{% trans "Enable Boot Menu for your instance when it starts up " %} - {% ifequal bootmenu 0 %} - <input type="submit" class="btn btn-success" name="set_bootmenu" title="Show boot menu" value="{% trans "Enable" %}"> - {% else %} - <input type="submit" class="btn btn-danger" name="unset_bootmenu" title="Hide boot menu" value="{% trans "Disable" %}"> - {% endifequal %} + <form class="form-horizontal" action="" method="post" role="form">{% csrf_token %} + <div class="form-group"> + <div class="col-sm-12 col-sm-offset-2"> + {% ifequal status 5 %} + <p>{% trans "Enable Boot Menu for your instance when it starts up " %} + {% ifequal bootmenu 0 %} + <input type="submit" class="btn btn-success" name="set_bootmenu" title="Show boot menu" value="{% trans "Enable" %}"> {% else %} - {% ifequal bootmenu 0 %} - <p>{% trans "**** Please shutdown instance to modify boot menu ****" %}</p> - {% endifequal %} + <input type="submit" class="btn btn-danger" name="unset_bootmenu" title="Hide boot menu" value="{% trans "Disable" %}"> {% endifequal %} - </div> + {% else %} + {% ifequal bootmenu 0 %} + <p>{% trans "**** Please shutdown instance to modify boot menu ****" %}</p> + {% endifequal %} + {% endifequal %} </div> - </form> - </p> + </div> + </form> + {% ifequal bootmenu 1 %} <div class="col-sm-6 col-sm-offset-2"> <div class="well"> @@ -841,12 +841,14 @@ <div class="col-xs-12 col-sm-12"> <table class="table table-hover"> <thead> - <th>{% trans "Device" %}</th> - <th>{% trans "Used" %}</th> - <th>{% trans "Capacity" %}</th> - <th>{% trans "Storage" %}</th> - <th>{% trans "Source" %}</th> - <th>{% trans "Action" %}</th> + <tr> + <th>{% trans "Device" %}</th> + <th>{% trans "Used" %}</th> + <th>{% trans "Capacity" %}</th> + <th>{% trans "Storage" %}</th> + <th>{% trans "Source" %}</th> + <th>{% trans "Action" %}</th> + </tr> </thead> <tbody> {% for disk in disks %} @@ -1169,7 +1171,7 @@ <button class="btn btn-lg btn-success pull-right disabled">{% trans "Migrate" %}</button> {% endif %} </form> - <div class="clearfix"></div></p> + <div class="clearfix"></div> </div> <div role="tabpanel" class="tab-pane tab-pane-bordered" id="xmledit"> <p>{% trans "If you need to edit xml please Power Off the instance" %}</p> @@ -1354,7 +1356,7 @@ </div> {% else %} <div class="col-sm-4"> - <select id="select_clone_name" class="form-control" name="name" size="1"/> + <select id="select_clone_name" class="form-control" name="name" size="1"> {% for name in clone_free_names %} <option value="{{ name }}">{{ name }}</option> {% endfor %} @@ -1730,7 +1732,7 @@ $.getJSON('{% url 'random_mac_address' %}', function (data) { $('input[name="' + net + '"]').val(data['mac']); }); - }; + } </script> <script> function show_console() { @@ -1765,13 +1767,13 @@ vname = '{{ vname }}'; {% for disk in disks %} disk_name = '{{ disk.image }}'; - disk_dot = disk_name.split('.') + disk_dot = disk_name.split('.'); disk_dot_suffix = disk_dot[disk_dot.length-1]; if (disk_name.startsWith(vname)) { image = disk_name.replace(vname, new_vname); } else if (disk_name.lastIndexOf('.') > -1 && disk_dot_suffix.length <= 7) { disk_dot.pop(); - disk_name_only = disk_dot.join('-') + disk_name_only = disk_dot.join('-'); image = new_vname + "-" + disk_name_only + "." + disk_dot_suffix } else if (new_vname != disk_name) { image = new_vname @@ -1811,28 +1813,28 @@ }); $(document).ready(function () { // set current console keymap or fall back to default - var keymap = "{{ console_keymap }}" + var keymap = "{{ console_keymap }}"; if (keymap != '') { $("#console_select_keymap option[value='" + keymap + "']").prop('selected', true); } }); $(document).ready(function () { // set current console type or fall back to default - var console_type = "{{ console_type }}" + var console_type = "{{ console_type }}"; if (console_type != '') { $("#console_select_type option[value='" + console_type + "']").prop('selected', true); } }); $(document).ready(function () { // set current console listen address or fall back to default - var console_listen_address = "{{ console_listen_address }}" + var console_listen_address = "{{ console_listen_address }}"; if (console_listen_address != '') { $("#console_select_listen_address option[value='" + console_listen_address + "']").prop('selected', true); } }); $(document).ready(function () { // get video model or fall back to default - let video_model = "{{ video_model }}" + let video_model = "{{ video_model }}"; if (video_model != '') { $("#video_model_select option[value='" + video_model + "']").prop('selected', true); } @@ -2103,7 +2105,7 @@ var netChart = {}; {% for net in networks %} var net_ctx_{{ forloop.counter0 }} = $("#netEth{{ forloop.counter0 }}Chart").get(0).getContext("2d"); - netChart['{{ forloop.counter0 }}'] = new Chart(net_ctx_{{ forloop.counter0 }}, { + netChart[{{ forloop.counter0 }}] = new Chart(net_ctx_{{ forloop.counter0 }}, { type: 'line', data: { datasets : [ @@ -2182,8 +2184,8 @@ for (let j = 0; j < data.blkdata.length; j++) { diskChart[data.blkdata[j].dev].data.labels.push(data.timeline); - diskChart[data.blkdata[j].dev].data.datasets[0].data.push(data.blkdata[0].data[0]); - diskChart[data.blkdata[j].dev].data.datasets[1].data.push(data.blkdata[0].data[1]); + diskChart[data.blkdata[j].dev].data.datasets[0].data.push(data.blkdata[j].data[0]); + diskChart[data.blkdata[j].dev].data.datasets[1].data.push(data.blkdata[j].data[1]); if (diskChart[data.blkdata[j].dev].data.datasets[0].data.length > 10){ diskChart[data.blkdata[j].dev].data.labels.shift(); diskChart[data.blkdata[j].dev].data.datasets[0].data.shift(); @@ -2195,8 +2197,8 @@ for (let j = 0; j < data.netdata.length; j++) { netChart[data.netdata[j].dev].data.labels.push(data.timeline); - netChart[data.netdata[j].dev].data.datasets[0].data.push(data.netdata[0].data[0]); - netChart[data.netdata[j].dev].data.datasets[1].data.push(data.netdata[0].data[1]); + netChart[data.netdata[j].dev].data.datasets[0].data.push(data.netdata[j].data[0]); + netChart[data.netdata[j].dev].data.datasets[1].data.push(data.netdata[j].data[1]); if (netChart[data.netdata[j].dev].data.datasets[0].data.length > 10){ netChart[data.netdata[j].dev].data.labels.shift(); netChart[data.netdata[j].dev].data.datasets[0].data.shift(); @@ -2211,7 +2213,7 @@ <script> backgroundJobRunning = false; window.setInterval(function get_status() { - var status = {{ status }}; + var status = {{ status|lower }}; $.getJSON('{% url 'inst_status' compute_id vname %}', function (data) { if (data['status'] != status && !backgroundJobRunning) { window.location.reload() diff --git a/instances/urls.py b/instances/urls.py index 1054ed1..32922a2 100644 --- a/instances/urls.py +++ b/instances/urls.py @@ -1,14 +1,14 @@ -from django.conf.urls import url +from django.urls import path, re_path from . import views urlpatterns = [ - url(r'^$', views.allinstances, name='allinstances'), - url(r'^(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.instance, name='instance'), - url(r'^statistics/(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.inst_graph, name='inst_graph'), - url(r'^status/(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.inst_status, name='inst_status'), - url(r'^guess_mac_address/(?P<vname>[\w\-\.]+)/$', views.guess_mac_address, name='guess_mac_address'), - url(r'^guess_clone_name/$', views.guess_clone_name, name='guess_clone_name'), - url(r'^random_mac_address/$', views.random_mac_address, name='random_mac_address'), - url(r'^check_instance/(?P<vname>[\w\-\.]+)/$', views.check_instance, name='check_instance'), - url(r'^sshkeys/(?P<vname>[\w\-\.]+)/$', views.sshkeys, name='sshkeys'), + path('', views.allinstances, name='allinstances'), + re_path(r'^(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.instance, name='instance'), + re_path(r'^statistics/(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.inst_graph, name='inst_graph'), + re_path(r'^status/(?P<compute_id>[0-9]+)/(?P<vname>[\w\-\.]+)/$', views.inst_status, name='inst_status'), + re_path(r'^guess_mac_address/(?P<vname>[\w\-\.]+)/$', views.guess_mac_address, name='guess_mac_address'), + re_path(r'^guess_clone_name/$', views.guess_clone_name, name='guess_clone_name'), + re_path(r'^random_mac_address/$', views.random_mac_address, name='random_mac_address'), + re_path(r'^check_instance/(?P<vname>[\w\-\.]+)/$', views.check_instance, name='check_instance'), + re_path(r'^sshkeys/(?P<vname>[\w\-\.]+)/$', views.sshkeys, name='sshkeys'), ] diff --git a/instances/views.py b/instances/views.py index 20d4616..7b9c51a 100644 --- a/instances/views.py +++ b/instances/views.py @@ -63,7 +63,7 @@ def allinstances(request): return instances_actions(request) except libvirtError as lib_err: error_messages.append(lib_err) - addlogmsg(request.user.username, request.POST.get("name", "instance"), lib_err.message) + addlogmsg(request.user.username, request.POST.get("name", "instance"), lib_err) view_style = settings.VIEW_INSTANCES_LIST_STYLE @@ -94,7 +94,7 @@ def instances(request, compute_id): return instances_actions(request) except libvirtError as lib_err: error_messages.append(lib_err) - addlogmsg(request.user.username, request.POST.get("name", "instance"), lib_err.message) + addlogmsg(request.user.username, request.POST.get("name", "instance"), lib_err) return render(request, 'instances.html', locals()) @@ -131,19 +131,19 @@ def instance(request, compute_id, vname): def filesizefstr(size_str): if size_str == '': return 0 - size_str = size_str.encode('ascii', 'ignore').upper().translate(None, " B") + size_str = size_str.upper().replace("B", "") if 'K' == size_str[-1]: - return long(float(size_str[:-1])) << 10 + return int(float(size_str[:-1])) << 10 elif 'M' == size_str[-1]: - return long(float(size_str[:-1])) << 20 + return int(float(size_str[:-1])) << 20 elif 'G' == size_str[-1]: - return long(float(size_str[:-1])) << 30 + return int(float(size_str[:-1])) << 30 elif 'T' == size_str[-1]: - return long(float(size_str[:-1])) << 40 + return int(float(size_str[:-1])) << 40 elif 'P' == size_str[-1]: - return long(float(size_str[:-1])) << 50 + return int(float(size_str[:-1])) << 50 else: - return long(float(size_str)) + return int(float(size_str)) def get_clone_free_names(size=10): prefix = settings.CLONE_INSTANCE_DEFAULT_PREFIX @@ -217,8 +217,8 @@ def instance(request, compute_id, vname): if media: existing_media_devs = [m['dev'] for m in media] - for l in string.lowercase: - dev = dev_base + l + for al in string.ascii_lowercase: + dev = dev_base + al if dev not in existing_disk_devs and dev not in existing_media_devs: return dev raise Exception(_('None available device name')) @@ -576,7 +576,7 @@ def instance(request, compute_id, vname): target_dev = get_new_disk_dev(media, disks, bus) source = conn_create.create_volume(storage, name, size, format, meta_prealloc, default_owner) - conn.attach_disk(source, target_dev, target_bus=bus, driver_type=format, cache_mode=cache) + conn.attach_disk(target_dev, source, target_bus=bus, driver_type=format, cache_mode=cache) msg = _('Attach new disk {} ({})'.format(name, format)) addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#disks') @@ -598,7 +598,7 @@ def instance(request, compute_id, vname): target_dev = get_new_disk_dev(media, disks, bus) source = path + "/" + name - conn.attach_disk(source, target_dev, target_bus=bus, driver_type=driver_type, cache_mode=cache) + conn.attach_disk(target_dev, source, target_bus=bus, driver_type=driver_type, cache_mode=cache) msg = _('Attach Existing disk: ' + target_dev) addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#disks') @@ -609,16 +609,26 @@ def instance(request, compute_id, vname): new_path = request.POST.get('vol_path', '') shareable = bool(request.POST.get('vol_shareable', False)) readonly = bool(request.POST.get('vol_readonly', False)) - bus = request.POST.get('vol_bus', '') + disk_type = request.POST.get('vol_type', '') + new_bus = request.POST.get('vol_bus', '') + bus = request.POST.get('vol_bus_old', '') serial = request.POST.get('vol_serial', '') format = request.POST.get('vol_format', '') cache = request.POST.get('vol_cache', default_cache) io = request.POST.get('vol_io_mode', default_io) discard = request.POST.get('vol_discard_mode', default_discard) zeroes = request.POST.get('vol_detect_zeroes', default_zeroes) + new_target_dev = get_new_disk_dev(media, disks, new_bus) - conn.edit_disk(target_dev, new_path, readonly, shareable, bus, serial, format, - cache, io, discard, zeroes) + if new_bus != bus: + conn.detach_disk(target_dev) + conn.attach_disk(new_target_dev, new_path, target_bus=new_bus, + driver_type=format, cache_mode=cache, + readonly=readonly, shareable=shareable, serial=serial, + io_mode=io, discard_mode=discard, detect_zeroes_mode=zeroes) + else: + conn.edit_disk(target_dev, new_path, readonly, shareable, new_bus, serial, format, + cache, io, discard, zeroes) if not conn.get_status() == 5: messages.success(request, _("Disk changes changes are applied. " + @@ -646,7 +656,7 @@ def instance(request, compute_id, vname): try: conn_delete.del_volume(name) except libvirtError as err: - msg = _('The disk: ' + dev + ' is detached but not deleted. ' + err.message) + msg = _('The disk: ' + dev + ' is detached but not deleted. ' + err) messages.warning(request, msg) addlogmsg(request.user.username, instance.name, msg) @@ -663,7 +673,7 @@ def instance(request, compute_id, vname): if 'add_cdrom' in request.POST and allow_admin_or_not_template: bus = request.POST.get('bus', 'ide' if machine == 'pc' else 'sata') target = get_new_disk_dev(media, disks, bus) - conn.attach_disk("", target, disk_device='cdrom', cache_mode='none', target_bus=bus, readonly=True) + conn.attach_disk(target, "", disk_device='cdrom', cache_mode='none', target_bus=bus, readonly=True) msg = _('Add CD-ROM: ' + target) addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#disks') @@ -746,7 +756,7 @@ def instance(request, compute_id, vname): try: conn.set_vcpu_hotplug(eval(status)) except libvirtError as lib_err: - messages.error(request, lib_err.message) + messages.error(request, lib_err) messages.success(request, msg) addlogmsg(request.user.username, instance.name, msg) return HttpResponseRedirect(request.get_full_path() + '#resize') @@ -951,7 +961,7 @@ def instance(request, compute_id, vname): "Stop and start network to activate new config") except libvirtError as le: - messages.error(request, le.message) + messages.error(request, le) return HttpResponseRedirect(request.get_full_path() + '#network') if 'unset_qos' in request.POST: qos_dir = request.POST.get('qos_direction', '') @@ -1028,13 +1038,13 @@ def instance(request, compute_id, vname): error_messages.append(msg) else: new_instance = Instance(compute_id=compute_id, name=clone_data['name']) - #new_instance.save() + # new_instance.save() try: new_uuid = conn.clone_instance(clone_data) new_instance.uuid = new_uuid new_instance.save() except Exception as e: - #new_instance.delete() + # new_instance.delete() raise e user_instance = UserInstance(instance_id=new_instance.id, user_id=request.user.id, is_delete=True) @@ -1064,8 +1074,8 @@ def instance(request, compute_id, vname): conn.close() except libvirtError as lib_err: - error_messages.append(lib_err.message) - addlogmsg(request.user.username, vname, lib_err.message) + error_messages.append(lib_err) + addlogmsg(request.user.username, vname, lib_err) return render(request, 'instance.html', locals()) @@ -1152,7 +1162,7 @@ def get_host_instances(request, comp): status = connection_manager.host_is_up(comp.type, comp.hostname) if status is True: - conn = wvmHostDetails(comp, comp.login, comp.password, comp.type) + conn = wvmHostDetails(comp.hostname, comp.login, comp.password, comp.type) comp_node_info = conn.get_node_info() comp_mem = conn.get_memory_usage() comp_instances = conn.get_host_instances(True) diff --git a/logs/migrations/0001_initial.py b/logs/migrations/0001_initial.py index 9acc8bf..21e66a8 100644 --- a/logs/migrations/0001_initial.py +++ b/logs/migrations/0001_initial.py @@ -1,29 +1,24 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals +# Generated by Django 2.2.10 on 2020-01-28 07:01 -from django.db import models, migrations -from django.conf import settings +from django.db import migrations, models class Migration(migrations.Migration): + initial = True + dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('instances', '0001_initial'), ] operations = [ migrations.CreateModel( name='Logs', fields=[ - ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('user', models.CharField(max_length=50)), + ('instance', models.CharField(max_length=50)), ('message', models.CharField(max_length=255)), ('date', models.DateTimeField(auto_now=True)), - ('instance', models.ForeignKey(to='instances.Instance')), - ('user', models.ForeignKey(to=settings.AUTH_USER_MODEL)), ], - options={ - }, - bases=(models.Model,), ), ] diff --git a/logs/migrations/0002_auto_20150316_1420.py b/logs/migrations/0002_auto_20150316_1420.py deleted file mode 100644 index 9b742d8..0000000 --- a/logs/migrations/0002_auto_20150316_1420.py +++ /dev/null @@ -1,28 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations -from django.conf import settings - - -class Migration(migrations.Migration): - - dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('logs', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='logs', - name='user', - field=models.ForeignKey(to=settings.AUTH_USER_MODEL), - preserve_default=False, - ), - migrations.AlterField( - model_name='logs', - name='date', - field=models.DateTimeField(auto_now=True), - preserve_default=True, - ), - ] diff --git a/logs/migrations/0003_auto_20150518_1855.py b/logs/migrations/0003_auto_20150518_1855.py deleted file mode 100644 index 4fb709c..0000000 --- a/logs/migrations/0003_auto_20150518_1855.py +++ /dev/null @@ -1,24 +0,0 @@ -# -*- coding: utf-8 -*- -from __future__ import unicode_literals - -from django.db import models, migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('logs', '0002_auto_20150316_1420'), - ] - - operations = [ - migrations.AlterField( - model_name='logs', - name='instance', - field=models.CharField(max_length=50), - ), - migrations.AlterField( - model_name='logs', - name='user', - field=models.CharField(max_length=50), - ), - ] diff --git a/logs/models.py b/logs/models.py index 57aa0a7..9125a62 100644 --- a/logs/models.py +++ b/logs/models.py @@ -1,11 +1,11 @@ -from django.db import models +from django.db.models import Model, CharField, DateTimeField -class Logs(models.Model): - user = models.CharField(max_length=50) - instance = models.CharField(max_length=50) - message = models.CharField(max_length=255) - date = models.DateTimeField(auto_now=True) +class Logs(Model): + user = CharField(max_length=50) + instance = CharField(max_length=50) + message = CharField(max_length=255) + date = DateTimeField(auto_now=True) def __unicode__(self): return self.instance diff --git a/logs/templates/paging.html b/logs/templates/paging.html index dc72a8c..9901dff 100644 --- a/logs/templates/paging.html +++ b/logs/templates/paging.html @@ -1,4 +1,4 @@ -<center> +<div class="center-block"> {% if page > 1 %} <a href="{% url 'showlogspage' page|add:"-1" %}">←</a> {% else %} @@ -9,4 +9,4 @@ {% else %} {% endif %} -</center> +</div> diff --git a/logs/urls.py b/logs/urls.py index 574405c..fb8fb0b 100644 --- a/logs/urls.py +++ b/logs/urls.py @@ -1,8 +1,8 @@ -from django.conf.urls import url +from django.urls import path, re_path from . import views urlpatterns = [ - url(r'^$', views.showlogs, name='showlogs'), - url(r'^(?P<page>[0-9]+)/$', views.showlogs, name='showlogspage'), - url(r'^vm_logs/(?P<vname>[\w\-\.]+)/$', views.vm_logs, name='vm_logs'), + path('', views.showlogs, name='showlogs'), + re_path(r'^(?P<page>[0-9]+)/$', views.showlogs, name='showlogspage'), + re_path(r'^vm_logs/(?P<vname>[\w\-\.]+)/$', views.vm_logs, name='vm_logs'), ] diff --git a/networks/forms.py b/networks/forms.py index 7c3b07d..fbf08bb 100644 --- a/networks/forms.py +++ b/networks/forms.py @@ -9,7 +9,7 @@ class AddNetPool(forms.Form): subnet = forms.CharField(error_messages={'required': _('No IPv4 subnet has been entered')}, max_length=20, required=False) subnet6 = forms.CharField(error_messages={'required': _('No IPv6 subnet has been entered')}, - max_length=42, required=False) + max_length=42, required=False) forward = forms.CharField(max_length=100) dhcp4 = forms.BooleanField(required=False) dhcp6 = forms.BooleanField(required=False) diff --git a/networks/templates/network.html b/networks/templates/network.html index 45aba51..5ebdd3f 100644 --- a/networks/templates/network.html +++ b/networks/templates/network.html @@ -191,6 +191,7 @@ <tbody style="text-align: center"> {% for fix4 in ipv4_fixed_address %} <tr> + <td> <form method="post" role="form">{% csrf_token %} <td><input class="form-control" value="{{ fix4.mac }}" name="mac" readonly/></td> <td><input class="form-control" value="{{ fix4.ip }}" name="address" /></td> @@ -209,6 +210,7 @@ </button> </td> </form> + </td> </tr> {% endfor %} </tbody> diff --git a/networks/views.py b/networks/views.py index acde835..a883be8 100644 --- a/networks/views.py +++ b/networks/views.py @@ -126,31 +126,31 @@ def network(request, compute_id, pool): conn.start() return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'stop' in request.POST: try: conn.stop() return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'delete' in request.POST: try: conn.delete() return HttpResponseRedirect(reverse('networks', args=[compute_id])) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'set_autostart' in request.POST: try: conn.set_autostart(1) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'unset_autostart' in request.POST: try: conn.set_autostart(0) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'modify_fixed_address' in request.POST: name = request.POST.get('name', '') address = request.POST.get('address', '') @@ -166,9 +166,9 @@ def network(request, compute_id, pool): messages.success(request, _("{} Fixed Address Operation Completed.").format(family.upper())) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) except ValueError as val_err: - error_messages.append(val_err.message) + error_messages.append(val_err) if 'delete_fixed_address' in request.POST: ip = request.POST.get('address', '') family = request.POST.get('family', 'ipv4') @@ -184,7 +184,7 @@ def network(request, compute_id, pool): messages.success(request, _("{} DHCP Range is Changed.").format(family.upper())) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'edit_network' in request.POST: edit_xml = request.POST.get('edit_xml', '') if edit_xml: @@ -208,8 +208,8 @@ def network(request, compute_id, pool): _("Stop and start network to activate new config")) else: messages.success(request, _("{} Qos is set").format(qos_dir.capitalize())) - except libvirtError as le: - messages.error(request, le.message) + except libvirtError as lib_err: + messages.error(request, lib_err) return HttpResponseRedirect(request.get_full_path()) if 'unset_qos' in request.POST: qos_dir = request.POST.get('qos_direction', '') diff --git a/nwfilters/templates/nwfilter.html b/nwfilters/templates/nwfilter.html index 18e04c6..fd46691 100644 --- a/nwfilters/templates/nwfilter.html +++ b/nwfilters/templates/nwfilter.html @@ -95,9 +95,11 @@ <div class="col-xs-12 col-sm-12"> <table class="table table-hover"> <thead> - <th style="width: 45px;">#</th> - <th>{% trans "Reference" %}</th> - <th>{% trans "Action" %}</th> + <tr> + <th style="width: 45px;">#</th> + <th>{% trans "Reference" %}</th> + <th>{% trans "Action" %}</th> + </tr> </thead> <tbody> {% for ref in refs %} @@ -125,6 +127,7 @@ <div class="col-xs-12 col-sm-12"> <table class="table table-hover"> <thead> + <tr> <th style="width:45px;">{% trans "Rule" %}</th> <th>{% trans "ActionType" %}</th> <th>{% trans "Direction" %}</th> @@ -132,6 +135,7 @@ <th>{% trans "Statematch" %}</th> <th>{% trans "Directives" %}</th> <th style="width:100px;">{% trans "Action" %}</th> + </tr> </thead> <tbody> {% for rule in rules %} diff --git a/nwfilters/views.py b/nwfilters/views.py index c8e35e8..3ee9163 100644 --- a/nwfilters/views.py +++ b/nwfilters/views.py @@ -59,8 +59,8 @@ def nwfilters(request, compute_id): conn.create_nwfilter(xml) addlogmsg(request.user.username, compute.hostname, msg) except libvirtError as lib_err: - error_messages.append(lib_err.message) - addlogmsg(request.user.username, compute.hostname, lib_err.message) + error_messages.append(lib_err) + addlogmsg(request.user.username, compute.hostname, lib_err) if 'del_nwfilter' in request.POST: name = request.POST.get('nwfiltername', '') diff --git a/secrets/views.py b/secrets/views.py index a21ffd8..d519ad9 100644 --- a/secrets/views.py +++ b/secrets/views.py @@ -22,13 +22,13 @@ def secrets(request, compute_id): secrets_all = [] error_messages = [] compute = get_object_or_404(Compute, pk=compute_id) - try: conn = wvmSecrets(compute.hostname, compute.login, compute.password, compute.type) secrets = conn.get_secrets() + for uuid in secrets: secrt = conn.get_secret(uuid) try: diff --git a/static/js/bootstrap-multiselect.js b/static/js/bootstrap-multiselect.js index ab1e2d6..e59b175 100644 --- a/static/js/bootstrap-multiselect.js +++ b/static/js/bootstrap-multiselect.js @@ -813,7 +813,7 @@ } $options.push(this.getOptionByValue(value)); - }, this)) + }, this)); // Cannot use select or deselect here because it would call updateOptGroups again. @@ -1608,7 +1608,7 @@ * Update opt groups. */ updateOptGroups: function() { - var $groups = $('li.multiselect-group', this.$ul) + var $groups = $('li.multiselect-group', this.$ul); var selectedClass = this.options.selectedClass; $groups.each(function() { diff --git a/static/js/novnc/app/styles/base.css b/static/js/novnc/app/styles/base.css index 2b31916..21e775e 100755 --- a/static/js/novnc/app/styles/base.css +++ b/static/js/novnc/app/styles/base.css @@ -22,7 +22,7 @@ body { margin:0; padding:0; - font-family: Helvetica; + font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; /*Background image with light grey curve.*/ background-color:#494949; background-repeat:no-repeat; diff --git a/static/js/novnc/vendor/browser-es-module-loader/dist/babel-worker.js b/static/js/novnc/vendor/browser-es-module-loader/dist/babel-worker.js index 3f9d7e0..9ccd019 100755 --- a/static/js/novnc/vendor/browser-es-module-loader/dist/babel-worker.js +++ b/static/js/novnc/vendor/browser-es-module-loader/dist/babel-worker.js @@ -6843,7 +6843,7 @@ var Printer = function () { var i = void 0; for (i = 0; i < str.length && str[i] === " "; i++) { - continue; + }if (i === str.length) return; var cha = str[i]; @@ -8008,9 +8008,9 @@ var ReplaceSupers = function () { var superRef = this.superRef || t.identifier("Function"); if (parent.property === id) { - return; + } else if (t.isCallExpression(parent, { callee: id })) { - return; + } else if (t.isMemberExpression(parent) && !methodNode.static) { return t.memberExpression(superRef, t.identifier("prototype")); } else { @@ -14914,7 +14914,7 @@ function evaluate() { return existing.value; } else { deopt(path); - return; + } } else { var item = { resolved: false }; @@ -15762,7 +15762,7 @@ var _loop = function _loop(type) { for (var type in virtualTypes) { var _ret = _loop(type); - if (_ret === "continue") continue; + if (_ret === "continue") } module.exports = exports["default"]; },{"../cache":115,"../index":118,"../scope":137,"./ancestry":119,"./comments":120,"./context":121,"./conversion":122,"./evaluation":123,"./family":124,"./inference":126,"./introspection":129,"./lib/virtual-types":132,"./modification":133,"./removal":134,"./replacement":135,"babel-runtime/core-js/get-iterator":95,"babel-runtime/helpers/classCallCheck":109,"babel-types":151,"debug":279,"invariant":292,"lodash/assign":463}],126:[function(require,module,exports){ @@ -16144,7 +16144,7 @@ function VariableDeclarator() { if (id.isIdentifier()) { return this.get("init").getTypeAnnotation(); } else { - return; + } } @@ -19257,7 +19257,7 @@ function wrapWithStateOrWrapper(oldVisitor, state, wrapper) { for (var key in oldVisitor) { var _ret = _loop(key); - if (_ret === "continue") continue; + if (_ret === "continue") } return newVisitor; @@ -30370,27 +30370,27 @@ function range(a, b, str) { } },{}],157:[function(require,module,exports){ -'use strict' +'use strict'; -exports.byteLength = byteLength -exports.toByteArray = toByteArray -exports.fromByteArray = fromByteArray +exports.byteLength = byteLength; +exports.toByteArray = toByteArray; +exports.fromByteArray = fromByteArray; -var lookup = [] -var revLookup = [] -var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array +var lookup = []; +var revLookup = []; +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array; -var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'; for (var i = 0, len = code.length; i < len; ++i) { - lookup[i] = code[i] + lookup[i] = code[i]; revLookup[code.charCodeAt(i)] = i } -revLookup['-'.charCodeAt(0)] = 62 -revLookup['_'.charCodeAt(0)] = 63 +revLookup['-'.charCodeAt(0)] = 62; +revLookup['_'.charCodeAt(0)] = 63; function placeHoldersCount (b64) { - var len = b64.length + var len = b64.length; if (len % 4 > 0) { throw new Error('Invalid string. Length must be a multiple of 4') } @@ -30409,30 +30409,30 @@ function byteLength (b64) { } function toByteArray (b64) { - var i, l, tmp, placeHolders, arr - var len = b64.length - placeHolders = placeHoldersCount(b64) + var i, l, tmp, placeHolders, arr; + var len = b64.length; + placeHolders = placeHoldersCount(b64); - arr = new Arr((len * 3 / 4) - placeHolders) + arr = new Arr((len * 3 / 4) - placeHolders); // if there are placeholders, only get up to the last complete 4 chars - l = placeHolders > 0 ? len - 4 : len + l = placeHolders > 0 ? len - 4 : len; - var L = 0 + var L = 0; for (i = 0; i < l; i += 4) { - tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)] - arr[L++] = (tmp >> 16) & 0xFF - arr[L++] = (tmp >> 8) & 0xFF + tmp = (revLookup[b64.charCodeAt(i)] << 18) | (revLookup[b64.charCodeAt(i + 1)] << 12) | (revLookup[b64.charCodeAt(i + 2)] << 6) | revLookup[b64.charCodeAt(i + 3)]; + arr[L++] = (tmp >> 16) & 0xFF; + arr[L++] = (tmp >> 8) & 0xFF; arr[L++] = tmp & 0xFF } if (placeHolders === 2) { - tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4) + tmp = (revLookup[b64.charCodeAt(i)] << 2) | (revLookup[b64.charCodeAt(i + 1)] >> 4); arr[L++] = tmp & 0xFF } else if (placeHolders === 1) { - tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[L++] = (tmp >> 8) & 0xFF + tmp = (revLookup[b64.charCodeAt(i)] << 10) | (revLookup[b64.charCodeAt(i + 1)] << 4) | (revLookup[b64.charCodeAt(i + 2)] >> 2); + arr[L++] = (tmp >> 8) & 0xFF; arr[L++] = tmp & 0xFF } @@ -30444,22 +30444,22 @@ function tripletToBase64 (num) { } function encodeChunk (uint8, start, end) { - var tmp - var output = [] + var tmp; + var output = []; for (var i = start; i < end; i += 3) { - tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]) + tmp = (uint8[i] << 16) + (uint8[i + 1] << 8) + (uint8[i + 2]); output.push(tripletToBase64(tmp)) } return output.join('') } function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var output = '' - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 + var tmp; + var len = uint8.length; + var extraBytes = len % 3; // if we have 1 byte left, pad 2 bytes + var output = ''; + var parts = []; + var maxChunkLength = 16383; // must be multiple of 3 // go through the array every three bytes, we'll deal with trailing stuff later for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { @@ -30468,19 +30468,19 @@ function fromByteArray (uint8) { // pad the end with zeros, but make sure to not forget the extra bytes if (extraBytes === 1) { - tmp = uint8[len - 1] - output += lookup[tmp >> 2] - output += lookup[(tmp << 4) & 0x3F] + tmp = uint8[len - 1]; + output += lookup[tmp >> 2]; + output += lookup[(tmp << 4) & 0x3F]; output += '==' } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + (uint8[len - 1]) - output += lookup[tmp >> 10] - output += lookup[(tmp >> 4) & 0x3F] - output += lookup[(tmp << 2) & 0x3F] + tmp = (uint8[len - 2] << 8) + (uint8[len - 1]); + output += lookup[tmp >> 10]; + output += lookup[(tmp >> 4) & 0x3F]; + output += lookup[(tmp << 2) & 0x3F]; output += '=' } - parts.push(output) + parts.push(output); return parts.join('') } @@ -30637,7 +30637,7 @@ function expand(str, isTop) { if (isSequence) { var x = numeric(n[0]); var y = numeric(n[1]); - var width = Math.max(n[0].length, n[1].length) + var width = Math.max(n[0].length, n[1].length); var incr = n.length == 3 ? Math.abs(numeric(n[2])) : 1; @@ -30700,15 +30700,15 @@ function expand(str, isTop) { */ /* eslint-disable no-proto */ -'use strict' +'use strict'; -var base64 = require('base64-js') -var ieee754 = require('ieee754') -var isArray = require('isarray') +var base64 = require('base64-js'); +var ieee754 = require('ieee754'); +var isArray = require('isarray'); -exports.Buffer = Buffer -exports.SlowBuffer = SlowBuffer -exports.INSPECT_MAX_BYTES = 50 +exports.Buffer = Buffer; +exports.SlowBuffer = SlowBuffer; +exports.INSPECT_MAX_BYTES = 50; /** * If `Buffer.TYPED_ARRAY_SUPPORT`: @@ -30736,17 +30736,17 @@ exports.INSPECT_MAX_BYTES = 50 */ Buffer.TYPED_ARRAY_SUPPORT = global.TYPED_ARRAY_SUPPORT !== undefined ? global.TYPED_ARRAY_SUPPORT - : typedArraySupport() + : typedArraySupport(); /* * Export kMaxLength after typed array support is determined. */ -exports.kMaxLength = kMaxLength() +exports.kMaxLength = kMaxLength(); function typedArraySupport () { try { - var arr = new Uint8Array(1) - arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }} + var arr = new Uint8Array(1); + arr.__proto__ = {__proto__: Uint8Array.prototype, foo: function () { return 42 }}; return arr.foo() === 42 && // typed array instances can be augmented typeof arr.subarray === 'function' && // chrome 9-10 lack `subarray` arr.subarray(1, 1).byteLength === 0 // ie10 has broken `subarray` @@ -30767,7 +30767,7 @@ function createBuffer (that, length) { } if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance - that = new Uint8Array(length) + that = new Uint8Array(length); that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class @@ -30807,13 +30807,13 @@ function Buffer (arg, encodingOrOffset, length) { return from(this, arg, encodingOrOffset, length) } -Buffer.poolSize = 8192 // not used by this implementation +Buffer.poolSize = 8192; // not used by this implementation // TODO: Legacy, not needed anymore. Remove in next major version. Buffer._augment = function (arr) { - arr.__proto__ = Buffer.prototype + arr.__proto__ = Buffer.prototype; return arr -} +}; function from (that, value, encodingOrOffset, length) { if (typeof value === 'number') { @@ -30841,11 +30841,11 @@ function from (that, value, encodingOrOffset, length) { **/ Buffer.from = function (value, encodingOrOffset, length) { return from(null, value, encodingOrOffset, length) -} +}; if (Buffer.TYPED_ARRAY_SUPPORT) { - Buffer.prototype.__proto__ = Uint8Array.prototype - Buffer.__proto__ = Uint8Array + Buffer.prototype.__proto__ = Uint8Array.prototype; + Buffer.__proto__ = Uint8Array; if (typeof Symbol !== 'undefined' && Symbol.species && Buffer[Symbol.species] === Buffer) { // Fix subarray() in ES2016. See: https://github.com/feross/buffer/pull/97 @@ -30865,7 +30865,7 @@ function assertSize (size) { } function alloc (that, size, fill, encoding) { - assertSize(size) + assertSize(size); if (size <= 0) { return createBuffer(that, size) } @@ -30886,11 +30886,11 @@ function alloc (that, size, fill, encoding) { **/ Buffer.alloc = function (size, fill, encoding) { return alloc(null, size, fill, encoding) -} +}; function allocUnsafe (that, size) { - assertSize(size) - that = createBuffer(that, size < 0 ? 0 : checked(size) | 0) + assertSize(size); + that = createBuffer(that, size < 0 ? 0 : checked(size) | 0); if (!Buffer.TYPED_ARRAY_SUPPORT) { for (var i = 0; i < size; ++i) { that[i] = 0 @@ -30904,13 +30904,13 @@ function allocUnsafe (that, size) { * */ Buffer.allocUnsafe = function (size) { return allocUnsafe(null, size) -} +}; /** * Equivalent to SlowBuffer(num), by default creates a non-zero-filled Buffer instance. */ Buffer.allocUnsafeSlow = function (size) { return allocUnsafe(null, size) -} +}; function fromString (that, string, encoding) { if (typeof encoding !== 'string' || encoding === '') { @@ -30921,10 +30921,10 @@ function fromString (that, string, encoding) { throw new TypeError('"encoding" must be a valid string encoding') } - var length = byteLength(string, encoding) | 0 - that = createBuffer(that, length) + var length = byteLength(string, encoding) | 0; + that = createBuffer(that, length); - var actual = that.write(string, encoding) + var actual = that.write(string, encoding); if (actual !== length) { // Writing a hex string, for example, that contains invalid characters will @@ -30937,8 +30937,8 @@ function fromString (that, string, encoding) { } function fromArrayLike (that, array) { - var length = array.length < 0 ? 0 : checked(array.length) | 0 - that = createBuffer(that, length) + var length = array.length < 0 ? 0 : checked(array.length) | 0; + that = createBuffer(that, length); for (var i = 0; i < length; i += 1) { that[i] = array[i] & 255 } @@ -30946,7 +30946,7 @@ function fromArrayLike (that, array) { } function fromArrayBuffer (that, array, byteOffset, length) { - array.byteLength // this throws if `array` is not a valid ArrayBuffer + array.byteLength; // this throws if `array` is not a valid ArrayBuffer if (byteOffset < 0 || array.byteLength < byteOffset) { throw new RangeError('\'offset\' is out of bounds') @@ -30966,7 +30966,7 @@ function fromArrayBuffer (that, array, byteOffset, length) { if (Buffer.TYPED_ARRAY_SUPPORT) { // Return an augmented `Uint8Array` instance, for best performance - that = array + that = array; that.__proto__ = Buffer.prototype } else { // Fallback: Return an object instance of the Buffer class @@ -30977,14 +30977,14 @@ function fromArrayBuffer (that, array, byteOffset, length) { function fromObject (that, obj) { if (Buffer.isBuffer(obj)) { - var len = checked(obj.length) | 0 - that = createBuffer(that, len) + var len = checked(obj.length) | 0; + that = createBuffer(that, len); if (that.length === 0) { return that } - obj.copy(that, 0, 0, len) + obj.copy(that, 0, 0, len); return that } @@ -31024,30 +31024,30 @@ function SlowBuffer (length) { Buffer.isBuffer = function isBuffer (b) { return !!(b != null && b._isBuffer) -} +}; Buffer.compare = function compare (a, b) { if (!Buffer.isBuffer(a) || !Buffer.isBuffer(b)) { throw new TypeError('Arguments must be Buffers') } - if (a === b) return 0 + if (a === b) return 0; - var x = a.length - var y = b.length + var x = a.length; + var y = b.length; for (var i = 0, len = Math.min(x, y); i < len; ++i) { if (a[i] !== b[i]) { - x = a[i] - y = b[i] + x = a[i]; + y = b[i]; break } } - if (x < y) return -1 - if (y < x) return 1 + if (x < y) return -1; + if (y < x) return 1; return 0 -} +}; Buffer.isEncoding = function isEncoding (encoding) { switch (String(encoding).toLowerCase()) { @@ -31062,11 +31062,11 @@ Buffer.isEncoding = function isEncoding (encoding) { case 'ucs-2': case 'utf16le': case 'utf-16le': - return true + return true; default: return false } -} +}; Buffer.concat = function concat (list, length) { if (!isArray(list)) { @@ -31077,26 +31077,26 @@ Buffer.concat = function concat (list, length) { return Buffer.alloc(0) } - var i + var i; if (length === undefined) { - length = 0 + length = 0; for (i = 0; i < list.length; ++i) { length += list[i].length } } - var buffer = Buffer.allocUnsafe(length) - var pos = 0 + var buffer = Buffer.allocUnsafe(length); + var pos = 0; for (i = 0; i < list.length; ++i) { - var buf = list[i] + var buf = list[i]; if (!Buffer.isBuffer(buf)) { throw new TypeError('"list" argument must be an Array of Buffers') } - buf.copy(buffer, pos) + buf.copy(buffer, pos); pos += buf.length } return buffer -} +}; function byteLength (string, encoding) { if (Buffer.isBuffer(string)) { @@ -31110,41 +31110,41 @@ function byteLength (string, encoding) { string = '' + string } - var len = string.length - if (len === 0) return 0 + var len = string.length; + if (len === 0) return 0; // Use a for loop to avoid recursion - var loweredCase = false + var loweredCase = false; for (;;) { switch (encoding) { case 'ascii': case 'latin1': case 'binary': - return len + return len; case 'utf8': case 'utf-8': case undefined: - return utf8ToBytes(string).length + return utf8ToBytes(string).length; case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': - return len * 2 + return len * 2; case 'hex': - return len >>> 1 + return len >>> 1; case 'base64': - return base64ToBytes(string).length + return base64ToBytes(string).length; default: - if (loweredCase) return utf8ToBytes(string).length // assume utf8 - encoding = ('' + encoding).toLowerCase() + if (loweredCase) return utf8ToBytes(string).length; // assume utf8 + encoding = ('' + encoding).toLowerCase(); loweredCase = true } } } -Buffer.byteLength = byteLength +Buffer.byteLength = byteLength; function slowToString (encoding, start, end) { - var loweredCase = false + var loweredCase = false; // No need to verify that "this.length <= MAX_UINT32" since it's a read-only // property of a typed array. @@ -31171,43 +31171,43 @@ function slowToString (encoding, start, end) { } // Force coersion to uint32. This will also coerce falsey/NaN values to 0. - end >>>= 0 - start >>>= 0 + end >>>= 0; + start >>>= 0; if (end <= start) { return '' } - if (!encoding) encoding = 'utf8' + if (!encoding) encoding = 'utf8'; while (true) { switch (encoding) { case 'hex': - return hexSlice(this, start, end) + return hexSlice(this, start, end); case 'utf8': case 'utf-8': - return utf8Slice(this, start, end) + return utf8Slice(this, start, end); case 'ascii': - return asciiSlice(this, start, end) + return asciiSlice(this, start, end); case 'latin1': case 'binary': - return latin1Slice(this, start, end) + return latin1Slice(this, start, end); case 'base64': - return base64Slice(this, start, end) + return base64Slice(this, start, end); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': - return utf16leSlice(this, start, end) + return utf16leSlice(this, start, end); default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = (encoding + '').toLowerCase() + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding); + encoding = (encoding + '').toLowerCase(); loweredCase = true } } @@ -31215,16 +31215,16 @@ function slowToString (encoding, start, end) { // The property is used by `Buffer.isBuffer` and `is-buffer` (in Safari 5-7) to detect // Buffer instances. -Buffer.prototype._isBuffer = true +Buffer.prototype._isBuffer = true; function swap (b, n, m) { - var i = b[n] - b[n] = b[m] + var i = b[n]; + b[n] = b[m]; b[m] = i } Buffer.prototype.swap16 = function swap16 () { - var len = this.length + var len = this.length; if (len % 2 !== 0) { throw new RangeError('Buffer size must be a multiple of 16-bits') } @@ -31232,56 +31232,56 @@ Buffer.prototype.swap16 = function swap16 () { swap(this, i, i + 1) } return this -} +}; Buffer.prototype.swap32 = function swap32 () { - var len = this.length + var len = this.length; if (len % 4 !== 0) { throw new RangeError('Buffer size must be a multiple of 32-bits') } for (var i = 0; i < len; i += 4) { - swap(this, i, i + 3) + swap(this, i, i + 3); swap(this, i + 1, i + 2) } return this -} +}; Buffer.prototype.swap64 = function swap64 () { - var len = this.length + var len = this.length; if (len % 8 !== 0) { throw new RangeError('Buffer size must be a multiple of 64-bits') } for (var i = 0; i < len; i += 8) { - swap(this, i, i + 7) - swap(this, i + 1, i + 6) - swap(this, i + 2, i + 5) + swap(this, i, i + 7); + swap(this, i + 1, i + 6); + swap(this, i + 2, i + 5); swap(this, i + 3, i + 4) } return this -} +}; Buffer.prototype.toString = function toString () { - var length = this.length | 0 - if (length === 0) return '' - if (arguments.length === 0) return utf8Slice(this, 0, length) + var length = this.length | 0; + if (length === 0) return ''; + if (arguments.length === 0) return utf8Slice(this, 0, length); return slowToString.apply(this, arguments) -} +}; Buffer.prototype.equals = function equals (b) { - if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer') - if (this === b) return true + if (!Buffer.isBuffer(b)) throw new TypeError('Argument must be a Buffer'); + if (this === b) return true; return Buffer.compare(this, b) === 0 -} +}; Buffer.prototype.inspect = function inspect () { - var str = '' - var max = exports.INSPECT_MAX_BYTES + var str = ''; + var max = exports.INSPECT_MAX_BYTES; if (this.length > 0) { - str = this.toString('hex', 0, max).match(/.{2}/g).join(' ') + str = this.toString('hex', 0, max).match(/.{2}/g).join(' '); if (this.length > max) str += ' ... ' } return '<Buffer ' + str + '>' -} +}; Buffer.prototype.compare = function compare (target, start, end, thisStart, thisEnd) { if (!Buffer.isBuffer(target)) { @@ -31315,32 +31315,32 @@ Buffer.prototype.compare = function compare (target, start, end, thisStart, this return 1 } - start >>>= 0 - end >>>= 0 - thisStart >>>= 0 - thisEnd >>>= 0 + start >>>= 0; + end >>>= 0; + thisStart >>>= 0; + thisEnd >>>= 0; - if (this === target) return 0 + if (this === target) return 0; - var x = thisEnd - thisStart - var y = end - start - var len = Math.min(x, y) + var x = thisEnd - thisStart; + var y = end - start; + var len = Math.min(x, y); - var thisCopy = this.slice(thisStart, thisEnd) - var targetCopy = target.slice(start, end) + var thisCopy = this.slice(thisStart, thisEnd); + var targetCopy = target.slice(start, end); for (var i = 0; i < len; ++i) { if (thisCopy[i] !== targetCopy[i]) { - x = thisCopy[i] - y = targetCopy[i] + x = thisCopy[i]; + y = targetCopy[i]; break } } - if (x < y) return -1 - if (y < x) return 1 + if (x < y) return -1; + if (y < x) return 1; return 0 -} +}; // Finds either the first index of `val` in `buffer` at offset >= `byteOffset`, // OR the last index of `val` in `buffer` at offset <= `byteOffset`. @@ -31353,30 +31353,30 @@ Buffer.prototype.compare = function compare (target, start, end, thisStart, this // - dir - true for indexOf, false for lastIndexOf function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { // Empty buffer means no match - if (buffer.length === 0) return -1 + if (buffer.length === 0) return -1; // Normalize byteOffset if (typeof byteOffset === 'string') { - encoding = byteOffset + encoding = byteOffset; byteOffset = 0 } else if (byteOffset > 0x7fffffff) { byteOffset = 0x7fffffff } else if (byteOffset < -0x80000000) { byteOffset = -0x80000000 } - byteOffset = +byteOffset // Coerce to Number. + byteOffset = +byteOffset; // Coerce to Number. if (isNaN(byteOffset)) { // byteOffset: it it's undefined, null, NaN, "foo", etc, search whole buffer byteOffset = dir ? 0 : (buffer.length - 1) } // Normalize byteOffset: negative offsets start from the end of the buffer - if (byteOffset < 0) byteOffset = buffer.length + byteOffset + if (byteOffset < 0) byteOffset = buffer.length + byteOffset; if (byteOffset >= buffer.length) { - if (dir) return -1 + if (dir) return -1; else byteOffset = buffer.length - 1 } else if (byteOffset < 0) { - if (dir) byteOffset = 0 + if (dir) byteOffset = 0; else return -1 } @@ -31393,7 +31393,7 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { } return arrayIndexOf(buffer, val, byteOffset, encoding, dir) } else if (typeof val === 'number') { - val = val & 0xFF // Search for a byte value [0-255] + val = val & 0xFF; // Search for a byte value [0-255] if (Buffer.TYPED_ARRAY_SUPPORT && typeof Uint8Array.prototype.indexOf === 'function') { if (dir) { @@ -31409,20 +31409,20 @@ function bidirectionalIndexOf (buffer, val, byteOffset, encoding, dir) { } function arrayIndexOf (arr, val, byteOffset, encoding, dir) { - var indexSize = 1 - var arrLength = arr.length - var valLength = val.length + var indexSize = 1; + var arrLength = arr.length; + var valLength = val.length; if (encoding !== undefined) { - encoding = String(encoding).toLowerCase() + encoding = String(encoding).toLowerCase(); if (encoding === 'ucs2' || encoding === 'ucs-2' || encoding === 'utf16le' || encoding === 'utf-16le') { if (arr.length < 2 || val.length < 2) { return -1 } - indexSize = 2 - arrLength /= 2 - valLength /= 2 + indexSize = 2; + arrLength /= 2; + valLength /= 2; byteOffset /= 2 } } @@ -31435,25 +31435,25 @@ function arrayIndexOf (arr, val, byteOffset, encoding, dir) { } } - var i + var i; if (dir) { - var foundIndex = -1 + var foundIndex = -1; for (i = byteOffset; i < arrLength; i++) { if (read(arr, i) === read(val, foundIndex === -1 ? 0 : i - foundIndex)) { - if (foundIndex === -1) foundIndex = i + if (foundIndex === -1) foundIndex = i; if (i - foundIndex + 1 === valLength) return foundIndex * indexSize } else { - if (foundIndex !== -1) i -= i - foundIndex + if (foundIndex !== -1) i -= i - foundIndex; foundIndex = -1 } } } else { - if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength + if (byteOffset + valLength > arrLength) byteOffset = arrLength - valLength; for (i = byteOffset; i >= 0; i--) { - var found = true + var found = true; for (var j = 0; j < valLength; j++) { if (read(arr, i + j) !== read(val, j)) { - found = false + found = false; break } } @@ -31466,38 +31466,38 @@ function arrayIndexOf (arr, val, byteOffset, encoding, dir) { Buffer.prototype.includes = function includes (val, byteOffset, encoding) { return this.indexOf(val, byteOffset, encoding) !== -1 -} +}; Buffer.prototype.indexOf = function indexOf (val, byteOffset, encoding) { return bidirectionalIndexOf(this, val, byteOffset, encoding, true) -} +}; Buffer.prototype.lastIndexOf = function lastIndexOf (val, byteOffset, encoding) { return bidirectionalIndexOf(this, val, byteOffset, encoding, false) -} +}; function hexWrite (buf, string, offset, length) { - offset = Number(offset) || 0 - var remaining = buf.length - offset + offset = Number(offset) || 0; + var remaining = buf.length - offset; if (!length) { length = remaining } else { - length = Number(length) + length = Number(length); if (length > remaining) { length = remaining } } // must be an even number of digits - var strLen = string.length - if (strLen % 2 !== 0) throw new TypeError('Invalid hex string') + var strLen = string.length; + if (strLen % 2 !== 0) throw new TypeError('Invalid hex string'); if (length > strLen / 2) { length = strLen / 2 } for (var i = 0; i < length; ++i) { - var parsed = parseInt(string.substr(i * 2, 2), 16) - if (isNaN(parsed)) return i + var parsed = parseInt(string.substr(i * 2, 2), 16); + if (isNaN(parsed)) return i; buf[offset + i] = parsed } return i @@ -31526,22 +31526,22 @@ function ucs2Write (buf, string, offset, length) { Buffer.prototype.write = function write (string, offset, length, encoding) { // Buffer#write(string) if (offset === undefined) { - encoding = 'utf8' - length = this.length + encoding = 'utf8'; + length = this.length; offset = 0 // Buffer#write(string, encoding) } else if (length === undefined && typeof offset === 'string') { - encoding = offset - length = this.length + encoding = offset; + length = this.length; offset = 0 // Buffer#write(string, offset[, length][, encoding]) } else if (isFinite(offset)) { - offset = offset | 0 + offset = offset | 0; if (isFinite(length)) { - length = length | 0 + length = length | 0; if (encoding === undefined) encoding = 'utf8' } else { - encoding = length + encoding = length; length = undefined } // legacy write(string, encoding, offset, length) - remove in v0.13 @@ -31551,56 +31551,56 @@ Buffer.prototype.write = function write (string, offset, length, encoding) { ) } - var remaining = this.length - offset - if (length === undefined || length > remaining) length = remaining + var remaining = this.length - offset; + if (length === undefined || length > remaining) length = remaining; if ((string.length > 0 && (length < 0 || offset < 0)) || offset > this.length) { throw new RangeError('Attempt to write outside buffer bounds') } - if (!encoding) encoding = 'utf8' + if (!encoding) encoding = 'utf8'; - var loweredCase = false + var loweredCase = false; for (;;) { switch (encoding) { case 'hex': - return hexWrite(this, string, offset, length) + return hexWrite(this, string, offset, length); case 'utf8': case 'utf-8': - return utf8Write(this, string, offset, length) + return utf8Write(this, string, offset, length); case 'ascii': - return asciiWrite(this, string, offset, length) + return asciiWrite(this, string, offset, length); case 'latin1': case 'binary': - return latin1Write(this, string, offset, length) + return latin1Write(this, string, offset, length); case 'base64': // Warning: maxLength not taken into account in base64Write - return base64Write(this, string, offset, length) + return base64Write(this, string, offset, length); case 'ucs2': case 'ucs-2': case 'utf16le': case 'utf-16le': - return ucs2Write(this, string, offset, length) + return ucs2Write(this, string, offset, length); default: - if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding) - encoding = ('' + encoding).toLowerCase() + if (loweredCase) throw new TypeError('Unknown encoding: ' + encoding); + encoding = ('' + encoding).toLowerCase(); loweredCase = true } } -} +}; Buffer.prototype.toJSON = function toJSON () { return { type: 'Buffer', data: Array.prototype.slice.call(this._arr || this, 0) } -} +}; function base64Slice (buf, start, end) { if (start === 0 && end === buf.length) { @@ -31611,52 +31611,52 @@ function base64Slice (buf, start, end) { } function utf8Slice (buf, start, end) { - end = Math.min(buf.length, end) - var res = [] + end = Math.min(buf.length, end); + var res = []; - var i = start + var i = start; while (i < end) { - var firstByte = buf[i] - var codePoint = null + var firstByte = buf[i]; + var codePoint = null; var bytesPerSequence = (firstByte > 0xEF) ? 4 : (firstByte > 0xDF) ? 3 : (firstByte > 0xBF) ? 2 - : 1 + : 1; if (i + bytesPerSequence <= end) { - var secondByte, thirdByte, fourthByte, tempCodePoint + var secondByte, thirdByte, fourthByte, tempCodePoint; switch (bytesPerSequence) { case 1: if (firstByte < 0x80) { codePoint = firstByte } - break + break; case 2: - secondByte = buf[i + 1] + secondByte = buf[i + 1]; if ((secondByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F) + tempCodePoint = (firstByte & 0x1F) << 0x6 | (secondByte & 0x3F); if (tempCodePoint > 0x7F) { codePoint = tempCodePoint } } - break + break; case 3: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] + secondByte = buf[i + 1]; + thirdByte = buf[i + 2]; if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F) + tempCodePoint = (firstByte & 0xF) << 0xC | (secondByte & 0x3F) << 0x6 | (thirdByte & 0x3F); if (tempCodePoint > 0x7FF && (tempCodePoint < 0xD800 || tempCodePoint > 0xDFFF)) { codePoint = tempCodePoint } } - break + break; case 4: - secondByte = buf[i + 1] - thirdByte = buf[i + 2] - fourthByte = buf[i + 3] + secondByte = buf[i + 1]; + thirdByte = buf[i + 2]; + fourthByte = buf[i + 3]; if ((secondByte & 0xC0) === 0x80 && (thirdByte & 0xC0) === 0x80 && (fourthByte & 0xC0) === 0x80) { - tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F) + tempCodePoint = (firstByte & 0xF) << 0x12 | (secondByte & 0x3F) << 0xC | (thirdByte & 0x3F) << 0x6 | (fourthByte & 0x3F); if (tempCodePoint > 0xFFFF && tempCodePoint < 0x110000) { codePoint = tempCodePoint } @@ -31667,16 +31667,16 @@ function utf8Slice (buf, start, end) { if (codePoint === null) { // we did not generate a valid codePoint so insert a // replacement char (U+FFFD) and advance only 1 byte - codePoint = 0xFFFD + codePoint = 0xFFFD; bytesPerSequence = 1 } else if (codePoint > 0xFFFF) { // encode to utf16 (surrogate pair dance) - codePoint -= 0x10000 - res.push(codePoint >>> 10 & 0x3FF | 0xD800) + codePoint -= 0x10000; + res.push(codePoint >>> 10 & 0x3FF | 0xD800); codePoint = 0xDC00 | codePoint & 0x3FF } - res.push(codePoint) + res.push(codePoint); i += bytesPerSequence } @@ -31686,17 +31686,17 @@ function utf8Slice (buf, start, end) { // Based on http://stackoverflow.com/a/22747272/680742, the browser with // the lowest limit is Chrome, with 0x10000 args. // We go 1 magnitude less, for safety -var MAX_ARGUMENTS_LENGTH = 0x1000 +var MAX_ARGUMENTS_LENGTH = 0x1000; function decodeCodePointsArray (codePoints) { - var len = codePoints.length + var len = codePoints.length; if (len <= MAX_ARGUMENTS_LENGTH) { return String.fromCharCode.apply(String, codePoints) // avoid extra slice() } // Decode in chunks to avoid "call stack size exceeded". - var res = '' - var i = 0 + var res = ''; + var i = 0; while (i < len) { res += String.fromCharCode.apply( String, @@ -31707,8 +31707,8 @@ function decodeCodePointsArray (codePoints) { } function asciiSlice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) + var ret = ''; + end = Math.min(buf.length, end); for (var i = start; i < end; ++i) { ret += String.fromCharCode(buf[i] & 0x7F) @@ -31717,8 +31717,8 @@ function asciiSlice (buf, start, end) { } function latin1Slice (buf, start, end) { - var ret = '' - end = Math.min(buf.length, end) + var ret = ''; + end = Math.min(buf.length, end); for (var i = start; i < end; ++i) { ret += String.fromCharCode(buf[i]) @@ -31727,12 +31727,12 @@ function latin1Slice (buf, start, end) { } function hexSlice (buf, start, end) { - var len = buf.length + var len = buf.length; - if (!start || start < 0) start = 0 - if (!end || end < 0 || end > len) end = len + if (!start || start < 0) start = 0; + if (!end || end < 0 || end > len) end = len; - var out = '' + var out = ''; for (var i = start; i < end; ++i) { out += toHex(buf[i]) } @@ -31740,8 +31740,8 @@ function hexSlice (buf, start, end) { } function utf16leSlice (buf, start, end) { - var bytes = buf.slice(start, end) - var res = '' + var bytes = buf.slice(start, end); + var res = ''; for (var i = 0; i < bytes.length; i += 2) { res += String.fromCharCode(bytes[i] + bytes[i + 1] * 256) } @@ -31749,260 +31749,260 @@ function utf16leSlice (buf, start, end) { } Buffer.prototype.slice = function slice (start, end) { - var len = this.length - start = ~~start - end = end === undefined ? len : ~~end + var len = this.length; + start = ~~start; + end = end === undefined ? len : ~~end; if (start < 0) { - start += len + start += len; if (start < 0) start = 0 } else if (start > len) { start = len } if (end < 0) { - end += len + end += len; if (end < 0) end = 0 } else if (end > len) { end = len } - if (end < start) end = start + if (end < start) end = start; - var newBuf + var newBuf; if (Buffer.TYPED_ARRAY_SUPPORT) { - newBuf = this.subarray(start, end) + newBuf = this.subarray(start, end); newBuf.__proto__ = Buffer.prototype } else { - var sliceLen = end - start - newBuf = new Buffer(sliceLen, undefined) + var sliceLen = end - start; + newBuf = new Buffer(sliceLen, undefined); for (var i = 0; i < sliceLen; ++i) { newBuf[i] = this[i + start] } } return newBuf -} +}; /* * Need to make sure that buffer isn't trying to write out of bounds. */ function checkOffset (offset, ext, length) { - if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint') + if ((offset % 1) !== 0 || offset < 0) throw new RangeError('offset is not uint'); if (offset + ext > length) throw new RangeError('Trying to access beyond buffer length') } Buffer.prototype.readUIntLE = function readUIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); - var val = this[offset] - var mul = 1 - var i = 0 + var val = this[offset]; + var mul = 1; + var i = 0; while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } return val -} +}; Buffer.prototype.readUIntBE = function readUIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 + offset = offset | 0; + byteLength = byteLength | 0; if (!noAssert) { checkOffset(offset, byteLength, this.length) } - var val = this[offset + --byteLength] - var mul = 1 + var val = this[offset + --byteLength]; + var mul = 1; while (byteLength > 0 && (mul *= 0x100)) { val += this[offset + --byteLength] * mul } return val -} +}; Buffer.prototype.readUInt8 = function readUInt8 (offset, noAssert) { - if (!noAssert) checkOffset(offset, 1, this.length) + if (!noAssert) checkOffset(offset, 1, this.length); return this[offset] -} +}; Buffer.prototype.readUInt16LE = function readUInt16LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) + if (!noAssert) checkOffset(offset, 2, this.length); return this[offset] | (this[offset + 1] << 8) -} +}; Buffer.prototype.readUInt16BE = function readUInt16BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) + if (!noAssert) checkOffset(offset, 2, this.length); return (this[offset] << 8) | this[offset + 1] -} +}; Buffer.prototype.readUInt32LE = function readUInt32LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + if (!noAssert) checkOffset(offset, 4, this.length); return ((this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16)) + (this[offset + 3] * 0x1000000) -} +}; Buffer.prototype.readUInt32BE = function readUInt32BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + if (!noAssert) checkOffset(offset, 4, this.length); return (this[offset] * 0x1000000) + ((this[offset + 1] << 16) | (this[offset + 2] << 8) | this[offset + 3]) -} +}; Buffer.prototype.readIntLE = function readIntLE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); - var val = this[offset] - var mul = 1 - var i = 0 + var val = this[offset]; + var mul = 1; + var i = 0; while (++i < byteLength && (mul *= 0x100)) { val += this[offset + i] * mul } - mul *= 0x80 + mul *= 0x80; - if (val >= mul) val -= Math.pow(2, 8 * byteLength) + if (val >= mul) val -= Math.pow(2, 8 * byteLength); return val -} +}; Buffer.prototype.readIntBE = function readIntBE (offset, byteLength, noAssert) { - offset = offset | 0 - byteLength = byteLength | 0 - if (!noAssert) checkOffset(offset, byteLength, this.length) + offset = offset | 0; + byteLength = byteLength | 0; + if (!noAssert) checkOffset(offset, byteLength, this.length); - var i = byteLength - var mul = 1 - var val = this[offset + --i] + var i = byteLength; + var mul = 1; + var val = this[offset + --i]; while (i > 0 && (mul *= 0x100)) { val += this[offset + --i] * mul } - mul *= 0x80 + mul *= 0x80; - if (val >= mul) val -= Math.pow(2, 8 * byteLength) + if (val >= mul) val -= Math.pow(2, 8 * byteLength); return val -} +}; Buffer.prototype.readInt8 = function readInt8 (offset, noAssert) { - if (!noAssert) checkOffset(offset, 1, this.length) - if (!(this[offset] & 0x80)) return (this[offset]) + if (!noAssert) checkOffset(offset, 1, this.length); + if (!(this[offset] & 0x80)) return (this[offset]); return ((0xff - this[offset] + 1) * -1) -} +}; Buffer.prototype.readInt16LE = function readInt16LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset] | (this[offset + 1] << 8) + if (!noAssert) checkOffset(offset, 2, this.length); + var val = this[offset] | (this[offset + 1] << 8); return (val & 0x8000) ? val | 0xFFFF0000 : val -} +}; Buffer.prototype.readInt16BE = function readInt16BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 2, this.length) - var val = this[offset + 1] | (this[offset] << 8) + if (!noAssert) checkOffset(offset, 2, this.length); + var val = this[offset + 1] | (this[offset] << 8); return (val & 0x8000) ? val | 0xFFFF0000 : val -} +}; Buffer.prototype.readInt32LE = function readInt32LE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + if (!noAssert) checkOffset(offset, 4, this.length); return (this[offset]) | (this[offset + 1] << 8) | (this[offset + 2] << 16) | (this[offset + 3] << 24) -} +}; Buffer.prototype.readInt32BE = function readInt32BE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + if (!noAssert) checkOffset(offset, 4, this.length); return (this[offset] << 24) | (this[offset + 1] << 16) | (this[offset + 2] << 8) | (this[offset + 3]) -} +}; Buffer.prototype.readFloatLE = function readFloatLE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + if (!noAssert) checkOffset(offset, 4, this.length); return ieee754.read(this, offset, true, 23, 4) -} +}; Buffer.prototype.readFloatBE = function readFloatBE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 4, this.length) + if (!noAssert) checkOffset(offset, 4, this.length); return ieee754.read(this, offset, false, 23, 4) -} +}; Buffer.prototype.readDoubleLE = function readDoubleLE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 8, this.length) + if (!noAssert) checkOffset(offset, 8, this.length); return ieee754.read(this, offset, true, 52, 8) -} +}; Buffer.prototype.readDoubleBE = function readDoubleBE (offset, noAssert) { - if (!noAssert) checkOffset(offset, 8, this.length) + if (!noAssert) checkOffset(offset, 8, this.length); return ieee754.read(this, offset, false, 52, 8) -} +}; function checkInt (buf, value, offset, ext, max, min) { - if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance') - if (value > max || value < min) throw new RangeError('"value" argument is out of bounds') + if (!Buffer.isBuffer(buf)) throw new TypeError('"buffer" argument must be a Buffer instance'); + if (value > max || value < min) throw new RangeError('"value" argument is out of bounds'); if (offset + ext > buf.length) throw new RangeError('Index out of range') } Buffer.prototype.writeUIntLE = function writeUIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - byteLength = byteLength | 0 + value = +value; + offset = offset | 0; + byteLength = byteLength | 0; if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 + var maxBytes = Math.pow(2, 8 * byteLength) - 1; checkInt(this, value, offset, byteLength, maxBytes, 0) } - var mul = 1 - var i = 0 - this[offset] = value & 0xFF + var mul = 1; + var i = 0; + this[offset] = value & 0xFF; while (++i < byteLength && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength -} +}; Buffer.prototype.writeUIntBE = function writeUIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 - byteLength = byteLength | 0 + value = +value; + offset = offset | 0; + byteLength = byteLength | 0; if (!noAssert) { - var maxBytes = Math.pow(2, 8 * byteLength) - 1 + var maxBytes = Math.pow(2, 8 * byteLength) - 1; checkInt(this, value, offset, byteLength, maxBytes, 0) } - var i = byteLength - 1 - var mul = 1 - this[offset + i] = value & 0xFF + var i = byteLength - 1; + var mul = 1; + this[offset + i] = value & 0xFF; while (--i >= 0 && (mul *= 0x100)) { this[offset + i] = (value / mul) & 0xFF } return offset + byteLength -} +}; Buffer.prototype.writeUInt8 = function writeUInt8 (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - this[offset] = (value & 0xff) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 1, 0xff, 0); + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); + this[offset] = (value & 0xff); return offset + 1 -} +}; function objectWriteUInt16 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffff + value + 1 + if (value < 0) value = 0xffff + value + 1; for (var i = 0, j = Math.min(buf.length - offset, 2); i < j; ++i) { buf[offset + i] = (value & (0xff << (8 * (littleEndian ? i : 1 - i)))) >>> (littleEndian ? i : 1 - i) * 8 @@ -32010,81 +32010,81 @@ function objectWriteUInt16 (buf, value, offset, littleEndian) { } Buffer.prototype.writeUInt16LE = function writeUInt16LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) + this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 -} +}; Buffer.prototype.writeUInt16BE = function writeUInt16BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 2, 0xffff, 0); if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) + this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff) } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 -} +}; function objectWriteUInt32 (buf, value, offset, littleEndian) { - if (value < 0) value = 0xffffffff + value + 1 + if (value < 0) value = 0xffffffff + value + 1; for (var i = 0, j = Math.min(buf.length - offset, 4); i < j; ++i) { buf[offset + i] = (value >>> (littleEndian ? i : 3 - i) * 8) & 0xff } } Buffer.prototype.writeUInt32LE = function writeUInt32LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset + 3] = (value >>> 24) - this[offset + 2] = (value >>> 16) - this[offset + 1] = (value >>> 8) + this[offset + 3] = (value >>> 24); + this[offset + 2] = (value >>> 16); + this[offset + 1] = (value >>> 8); this[offset] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 -} +}; Buffer.prototype.writeUInt32BE = function writeUInt32BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 4, 0xffffffff, 0); if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) + this[offset] = (value >>> 24); + this[offset + 1] = (value >>> 16); + this[offset + 2] = (value >>> 8); this[offset + 3] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 -} +}; Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 + value = +value; + offset = offset | 0; if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) + var limit = Math.pow(2, 8 * byteLength - 1); checkInt(this, value, offset, byteLength, limit - 1, -limit) } - var i = 0 - var mul = 1 - var sub = 0 - this[offset] = value & 0xFF + var i = 0; + var mul = 1; + var sub = 0; + this[offset] = value & 0xFF; while (++i < byteLength && (mul *= 0x100)) { if (value < 0 && sub === 0 && this[offset + i - 1] !== 0) { sub = 1 @@ -32093,21 +32093,21 @@ Buffer.prototype.writeIntLE = function writeIntLE (value, offset, byteLength, no } return offset + byteLength -} +}; Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, noAssert) { - value = +value - offset = offset | 0 + value = +value; + offset = offset | 0; if (!noAssert) { - var limit = Math.pow(2, 8 * byteLength - 1) + var limit = Math.pow(2, 8 * byteLength - 1); checkInt(this, value, offset, byteLength, limit - 1, -limit) } - var i = byteLength - 1 - var mul = 1 - var sub = 0 - this[offset + i] = value & 0xFF + var i = byteLength - 1; + var mul = 1; + var sub = 0; + this[offset + i] = value & 0xFF; while (--i >= 0 && (mul *= 0x100)) { if (value < 0 && sub === 0 && this[offset + i + 1] !== 0) { sub = 1 @@ -32116,77 +32116,77 @@ Buffer.prototype.writeIntBE = function writeIntBE (value, offset, byteLength, no } return offset + byteLength -} +}; Buffer.prototype.writeInt8 = function writeInt8 (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80) - if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value) - if (value < 0) value = 0xff + value + 1 - this[offset] = (value & 0xff) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 1, 0x7f, -0x80); + if (!Buffer.TYPED_ARRAY_SUPPORT) value = Math.floor(value); + if (value < 0) value = 0xff + value + 1; + this[offset] = (value & 0xff); return offset + 1 -} +}; Buffer.prototype.writeInt16LE = function writeInt16LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) + this[offset] = (value & 0xff); this[offset + 1] = (value >>> 8) } else { objectWriteUInt16(this, value, offset, true) } return offset + 2 -} +}; Buffer.prototype.writeInt16BE = function writeInt16BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 2, 0x7fff, -0x8000); if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 8) + this[offset] = (value >>> 8); this[offset + 1] = (value & 0xff) } else { objectWriteUInt16(this, value, offset, false) } return offset + 2 -} +}; Buffer.prototype.writeInt32LE = function writeInt32LE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value & 0xff) - this[offset + 1] = (value >>> 8) - this[offset + 2] = (value >>> 16) + this[offset] = (value & 0xff); + this[offset + 1] = (value >>> 8); + this[offset + 2] = (value >>> 16); this[offset + 3] = (value >>> 24) } else { objectWriteUInt32(this, value, offset, true) } return offset + 4 -} +}; Buffer.prototype.writeInt32BE = function writeInt32BE (value, offset, noAssert) { - value = +value - offset = offset | 0 - if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000) - if (value < 0) value = 0xffffffff + value + 1 + value = +value; + offset = offset | 0; + if (!noAssert) checkInt(this, value, offset, 4, 0x7fffffff, -0x80000000); + if (value < 0) value = 0xffffffff + value + 1; if (Buffer.TYPED_ARRAY_SUPPORT) { - this[offset] = (value >>> 24) - this[offset + 1] = (value >>> 16) - this[offset + 2] = (value >>> 8) + this[offset] = (value >>> 24); + this[offset + 1] = (value >>> 16); + this[offset + 2] = (value >>> 8); this[offset + 3] = (value & 0xff) } else { objectWriteUInt32(this, value, offset, false) } return offset + 4 -} +}; function checkIEEE754 (buf, value, offset, ext, max, min) { - if (offset + ext > buf.length) throw new RangeError('Index out of range') + if (offset + ext > buf.length) throw new RangeError('Index out of range'); if (offset < 0) throw new RangeError('Index out of range') } @@ -32194,61 +32194,61 @@ function writeFloat (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 4, 3.4028234663852886e+38, -3.4028234663852886e+38) } - ieee754.write(buf, value, offset, littleEndian, 23, 4) + ieee754.write(buf, value, offset, littleEndian, 23, 4); return offset + 4 } Buffer.prototype.writeFloatLE = function writeFloatLE (value, offset, noAssert) { return writeFloat(this, value, offset, true, noAssert) -} +}; Buffer.prototype.writeFloatBE = function writeFloatBE (value, offset, noAssert) { return writeFloat(this, value, offset, false, noAssert) -} +}; function writeDouble (buf, value, offset, littleEndian, noAssert) { if (!noAssert) { checkIEEE754(buf, value, offset, 8, 1.7976931348623157E+308, -1.7976931348623157E+308) } - ieee754.write(buf, value, offset, littleEndian, 52, 8) + ieee754.write(buf, value, offset, littleEndian, 52, 8); return offset + 8 } Buffer.prototype.writeDoubleLE = function writeDoubleLE (value, offset, noAssert) { return writeDouble(this, value, offset, true, noAssert) -} +}; Buffer.prototype.writeDoubleBE = function writeDoubleBE (value, offset, noAssert) { return writeDouble(this, value, offset, false, noAssert) -} +}; // copy(targetBuffer, targetStart=0, sourceStart=0, sourceEnd=buffer.length) Buffer.prototype.copy = function copy (target, targetStart, start, end) { - if (!start) start = 0 - if (!end && end !== 0) end = this.length - if (targetStart >= target.length) targetStart = target.length - if (!targetStart) targetStart = 0 - if (end > 0 && end < start) end = start + if (!start) start = 0; + if (!end && end !== 0) end = this.length; + if (targetStart >= target.length) targetStart = target.length; + if (!targetStart) targetStart = 0; + if (end > 0 && end < start) end = start; // Copy 0 bytes; we're done - if (end === start) return 0 - if (target.length === 0 || this.length === 0) return 0 + if (end === start) return 0; + if (target.length === 0 || this.length === 0) return 0; // Fatal error conditions if (targetStart < 0) { throw new RangeError('targetStart out of bounds') } - if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds') - if (end < 0) throw new RangeError('sourceEnd out of bounds') + if (start < 0 || start >= this.length) throw new RangeError('sourceStart out of bounds'); + if (end < 0) throw new RangeError('sourceEnd out of bounds'); // Are we oob? - if (end > this.length) end = this.length + if (end > this.length) end = this.length; if (target.length - targetStart < end - start) { end = target.length - targetStart + start } - var len = end - start - var i + var len = end - start; + var i; if (this === target && start < targetStart && targetStart < end) { // descending copy from end @@ -32269,7 +32269,7 @@ Buffer.prototype.copy = function copy (target, targetStart, start, end) { } return len -} +}; // Usage: // buffer.fill(number[, offset[, end]]) @@ -32279,15 +32279,15 @@ Buffer.prototype.fill = function fill (val, start, end, encoding) { // Handle string cases: if (typeof val === 'string') { if (typeof start === 'string') { - encoding = start - start = 0 + encoding = start; + start = 0; end = this.length } else if (typeof end === 'string') { - encoding = end + encoding = end; end = this.length } if (val.length === 1) { - var code = val.charCodeAt(0) + var code = val.charCodeAt(0); if (code < 256) { val = code } @@ -32311,12 +32311,12 @@ Buffer.prototype.fill = function fill (val, start, end, encoding) { return this } - start = start >>> 0 - end = end === undefined ? this.length : end >>> 0 + start = start >>> 0; + end = end === undefined ? this.length : end >>> 0; - if (!val) val = 0 + if (!val) val = 0; - var i + var i; if (typeof val === 'number') { for (i = start; i < end; ++i) { this[i] = val @@ -32324,26 +32324,26 @@ Buffer.prototype.fill = function fill (val, start, end, encoding) { } else { var bytes = Buffer.isBuffer(val) ? val - : utf8ToBytes(new Buffer(val, encoding).toString()) - var len = bytes.length + : utf8ToBytes(new Buffer(val, encoding).toString()); + var len = bytes.length; for (i = 0; i < end - start; ++i) { this[i + start] = bytes[i % len] } } return this -} +}; // HELPER FUNCTIONS // ================ -var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g +var INVALID_BASE64_RE = /[^+\/0-9A-Za-z-_]/g; function base64clean (str) { // Node strips out invalid characters like \n and \t from the string, base64-js does not - str = stringtrim(str).replace(INVALID_BASE64_RE, '') + str = stringtrim(str).replace(INVALID_BASE64_RE, ''); // Node converts strings with length < 2 to '' - if (str.length < 2) return '' + if (str.length < 2) return ''; // Node allows for non-padded base64 strings (missing trailing ===), base64-js does not while (str.length % 4 !== 0) { str = str + '=' @@ -32352,24 +32352,24 @@ function base64clean (str) { } function stringtrim (str) { - if (str.trim) return str.trim() + if (str.trim) return str.trim(); return str.replace(/^\s+|\s+$/g, '') } function toHex (n) { - if (n < 16) return '0' + n.toString(16) + if (n < 16) return '0' + n.toString(16); return n.toString(16) } function utf8ToBytes (string, units) { - units = units || Infinity - var codePoint - var length = string.length - var leadSurrogate = null - var bytes = [] + units = units || Infinity; + var codePoint; + var length = string.length; + var leadSurrogate = null; + var bytes = []; for (var i = 0; i < length; ++i) { - codePoint = string.charCodeAt(i) + codePoint = string.charCodeAt(i); // is surrogate component if (codePoint > 0xD7FF && codePoint < 0xE000) { @@ -32378,24 +32378,24 @@ function utf8ToBytes (string, units) { // no lead yet if (codePoint > 0xDBFF) { // unexpected trail - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); continue } else if (i + 1 === length) { // unpaired lead - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); continue } // valid lead - leadSurrogate = codePoint + leadSurrogate = codePoint; continue } // 2 leads in a row if (codePoint < 0xDC00) { - if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) - leadSurrogate = codePoint + if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD); + leadSurrogate = codePoint; continue } @@ -32406,27 +32406,27 @@ function utf8ToBytes (string, units) { if ((units -= 3) > -1) bytes.push(0xEF, 0xBF, 0xBD) } - leadSurrogate = null + leadSurrogate = null; // encode utf8 if (codePoint < 0x80) { - if ((units -= 1) < 0) break + if ((units -= 1) < 0) break; bytes.push(codePoint) } else if (codePoint < 0x800) { - if ((units -= 2) < 0) break + if ((units -= 2) < 0) break; bytes.push( codePoint >> 0x6 | 0xC0, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x10000) { - if ((units -= 3) < 0) break + if ((units -= 3) < 0) break; bytes.push( codePoint >> 0xC | 0xE0, codePoint >> 0x6 & 0x3F | 0x80, codePoint & 0x3F | 0x80 ) } else if (codePoint < 0x110000) { - if ((units -= 4) < 0) break + if ((units -= 4) < 0) break; bytes.push( codePoint >> 0x12 | 0xF0, codePoint >> 0xC & 0x3F | 0x80, @@ -32442,7 +32442,7 @@ function utf8ToBytes (string, units) { } function asciiToBytes (str) { - var byteArray = [] + var byteArray = []; for (var i = 0; i < str.length; ++i) { // Node's code seems to be doing this and not & 0x7F.. byteArray.push(str.charCodeAt(i) & 0xFF) @@ -32451,15 +32451,15 @@ function asciiToBytes (str) { } function utf16leToBytes (str, units) { - var c, hi, lo - var byteArray = [] + var c, hi, lo; + var byteArray = []; for (var i = 0; i < str.length; ++i) { - if ((units -= 2) < 0) break + if ((units -= 2) < 0) break; - c = str.charCodeAt(i) - hi = c >> 8 - lo = c % 256 - byteArray.push(lo) + c = str.charCodeAt(i); + hi = c >> 8; + lo = c % 256; + byteArray.push(lo); byteArray.push(hi) } @@ -32472,7 +32472,7 @@ function base64ToBytes (str) { function blitBuffer (src, dst, offset, length) { for (var i = 0; i < length; ++i) { - if ((i + offset >= dst.length) || (i >= src.length)) break + if ((i + offset >= dst.length) || (i >= src.length)) break; dst[i + offset] = src[i] } return i @@ -34767,7 +34767,7 @@ function formatArgs(args) { if (!useColors) return; var c = 'color: ' + this.color; - args.splice(1, 0, c, 'color: inherit') + args.splice(1, 0, c, 'color: inherit'); // the final "%c" is somewhat tricky, because there could be other // arguments passed either before or after the %c, so we need to @@ -37247,25 +37247,25 @@ module.exports = re.test.bind(re); },{"ansi-regex":1}],291:[function(require,module,exports){ exports.read = function (buffer, offset, isLE, mLen, nBytes) { - var e, m - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var nBits = -7 - var i = isLE ? (nBytes - 1) : 0 - var d = isLE ? -1 : 1 - var s = buffer[offset + i] + var e, m; + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var nBits = -7; + var i = isLE ? (nBytes - 1) : 0; + var d = isLE ? -1 : 1; + var s = buffer[offset + i]; - i += d + i += d; - e = s & ((1 << (-nBits)) - 1) - s >>= (-nBits) - nBits += eLen + e = s & ((1 << (-nBits)) - 1); + s >>= (-nBits); + nBits += eLen; for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8) {} - m = e & ((1 << (-nBits)) - 1) - e >>= (-nBits) - nBits += mLen + m = e & ((1 << (-nBits)) - 1); + e >>= (-nBits); + nBits += mLen; for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8) {} if (e === 0) { @@ -37273,31 +37273,31 @@ exports.read = function (buffer, offset, isLE, mLen, nBytes) { } else if (e === eMax) { return m ? NaN : ((s ? -1 : 1) * Infinity) } else { - m = m + Math.pow(2, mLen) + m = m + Math.pow(2, mLen); e = e - eBias } return (s ? -1 : 1) * m * Math.pow(2, e - mLen) -} +}; exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { - var e, m, c - var eLen = nBytes * 8 - mLen - 1 - var eMax = (1 << eLen) - 1 - var eBias = eMax >> 1 - var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0) - var i = isLE ? 0 : (nBytes - 1) - var d = isLE ? 1 : -1 - var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0 + var e, m, c; + var eLen = nBytes * 8 - mLen - 1; + var eMax = (1 << eLen) - 1; + var eBias = eMax >> 1; + var rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0); + var i = isLE ? 0 : (nBytes - 1); + var d = isLE ? 1 : -1; + var s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0; - value = Math.abs(value) + value = Math.abs(value); if (isNaN(value) || value === Infinity) { - m = isNaN(value) ? 1 : 0 + m = isNaN(value) ? 1 : 0; e = eMax } else { - e = Math.floor(Math.log(value) / Math.LN2) + e = Math.floor(Math.log(value) / Math.LN2); if (value * (c = Math.pow(2, -e)) < 1) { - e-- + e--; c *= 2 } if (e + eBias >= 1) { @@ -37306,26 +37306,26 @@ exports.write = function (buffer, value, offset, isLE, mLen, nBytes) { value += rt * Math.pow(2, 1 - eBias) } if (value * c >= 2) { - e++ + e++; c /= 2 } if (e + eBias >= eMax) { - m = 0 + m = 0; e = eMax } else if (e + eBias >= 1) { - m = (value * c - 1) * Math.pow(2, mLen) + m = (value * c - 1) * Math.pow(2, mLen); e = e + eBias } else { - m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen) + m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen); e = 0 } } for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8) {} - e = (e << mLen) | m - eLen += mLen + e = (e << mLen) | m; + eLen += mLen; for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8) {} buffer[offset + i - d] |= s * 128 @@ -37407,22 +37407,22 @@ module.exports = Array.isArray || function (arr) { Object.defineProperty(exports, "__esModule", { value: true -}) +}); // This regex comes from regex.coffee, and is inserted here by generate-index.js // (run `npm run build`). -exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyu]{1,5}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g +exports.default = /((['"])(?:(?!\2|\\).|\\(?:\r\n|[\s\S]))*(\2)?|`(?:[^`\\$]|\\[\s\S]|\$(?!\{)|\$\{(?:[^{}]|\{[^}]*\}?)*\}?)*(`)?)|(\/\/.*)|(\/\*(?:[^*]|\*(?!\/))*(\*\/)?)|(\/(?!\*)(?:\[(?:(?![\]\\]).|\\.)*\]|(?![\/\]\\]).|\\.)+\/(?:(?!\s*(?:\b|[\u0080-\uFFFF$\\'"~({]|[+\-!](?!=)|\.?\d))|[gmiyu]{1,5}\b(?![\u0080-\uFFFF$\\]|\s*(?:[+\-*%&|^<>!=?({]|\/(?![\/*])))))|(0[xX][\da-fA-F]+|0[oO][0-7]+|0[bB][01]+|(?:\d*\.\d+|\d+\.?)(?:[eE][+-]?\d+)?)|((?!\d)(?:(?!\s)[$\w\u0080-\uFFFF]|\\u[\da-fA-F]{4}|\\u\{[\da-fA-F]+\})+)|(--|\+\+|&&|\|\||=>|\.{3}|(?:[+\-\/%&|^]|\*{1,2}|<{1,2}|>{1,3}|!=?|={1,2})=?|[?~.,:;[\](){}])|(\s+)|(^$|[\s\S])/g; exports.matchToToken = function(match) { - var token = {type: "invalid", value: match[0]} - if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4]) - else if (match[ 5]) token.type = "comment" - else if (match[ 6]) token.type = "comment", token.closed = !!match[7] - else if (match[ 8]) token.type = "regex" - else if (match[ 9]) token.type = "number" - else if (match[10]) token.type = "name" - else if (match[11]) token.type = "punctuator" - else if (match[12]) token.type = "whitespace" + var token = {type: "invalid", value: match[0]}; + if (match[ 1]) token.type = "string" , token.closed = !!(match[3] || match[4]); + else if (match[ 5]) token.type = "comment"; + else if (match[ 6]) token.type = "comment", token.closed = !!match[7]; + else if (match[ 8]) token.type = "regex"; + else if (match[ 9]) token.type = "number"; + else if (match[10]) token.type = "name"; + else if (match[11]) token.type = "punctuator"; + else if (match[12]) token.type = "whitespace"; return token } @@ -37736,7 +37736,7 @@ exports.matchToToken = function(match) { var escaped = '\\' + (longhand ? 'u' : 'x') + ('0000' + hexadecimal).slice(longhand ? -4 : -2); result += escaped; - continue; + } if (options.wrap) { result = quote + result + quote; @@ -45311,16 +45311,16 @@ function values(object) { module.exports = values; },{"./_baseValues":371,"./keys":498}],519:[function(require,module,exports){ -module.exports = minimatch -minimatch.Minimatch = Minimatch +module.exports = minimatch; +minimatch.Minimatch = Minimatch; -var path = { sep: '/' } +var path = { sep: '/' }; try { path = require('path') } catch (er) {} -var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {} -var expand = require('brace-expansion') +var GLOBSTAR = minimatch.GLOBSTAR = Minimatch.GLOBSTAR = {}; +var expand = require('brace-expansion'); var plTypes = { '!': { open: '(?:(?!(?:', close: '))[^/]*?)'}, @@ -45328,86 +45328,86 @@ var plTypes = { '+': { open: '(?:', close: ')+' }, '*': { open: '(?:', close: ')*' }, '@': { open: '(?:', close: ')' } -} +}; // any single thing other than / // don't need to escape / when using new RegExp() -var qmark = '[^/]' +var qmark = '[^/]'; // * => any number of characters -var star = qmark + '*?' +var star = qmark + '*?'; // ** when dots are allowed. Anything goes, except .. and . // not (^ or / followed by one or two dots followed by $ or /), // followed by anything, any number of times. -var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?' +var twoStarDot = '(?:(?!(?:\\\/|^)(?:\\.{1,2})($|\\\/)).)*?'; // not a ^ or / followed by a dot, // followed by anything, any number of times. -var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?' +var twoStarNoDot = '(?:(?!(?:\\\/|^)\\.).)*?'; // characters that need to be escaped in RegExp. -var reSpecials = charSet('().*{}+?[]^$\\!') +var reSpecials = charSet('().*{}+?[]^$\\!'); // "abc" -> { a:true, b:true, c:true } function charSet (s) { return s.split('').reduce(function (set, c) { - set[c] = true + set[c] = true; return set }, {}) } // normalizes slashes. -var slashSplit = /\/+/ +var slashSplit = /\/+/; -minimatch.filter = filter +minimatch.filter = filter; function filter (pattern, options) { - options = options || {} + options = options || {}; return function (p, i, list) { return minimatch(p, pattern, options) } } function ext (a, b) { - a = a || {} - b = b || {} - var t = {} + a = a || {}; + b = b || {}; + var t = {}; Object.keys(b).forEach(function (k) { t[k] = b[k] - }) + }); Object.keys(a).forEach(function (k) { t[k] = a[k] - }) + }); return t } minimatch.defaults = function (def) { - if (!def || !Object.keys(def).length) return minimatch + if (!def || !Object.keys(def).length) return minimatch; - var orig = minimatch + var orig = minimatch; var m = function minimatch (p, pattern, options) { return orig.minimatch(p, pattern, ext(def, options)) - } + }; m.Minimatch = function Minimatch (pattern, options) { return new orig.Minimatch(pattern, ext(def, options)) - } + }; return m -} +}; Minimatch.defaults = function (def) { - if (!def || !Object.keys(def).length) return Minimatch + if (!def || !Object.keys(def).length) return Minimatch; return minimatch.defaults(def).Minimatch -} +}; function minimatch (p, pattern, options) { if (typeof pattern !== 'string') { throw new TypeError('glob pattern string required') } - if (!options) options = {} + if (!options) options = {}; // shortcut: comments match nothing. if (!options.nocomment && pattern.charAt(0) === '#') { @@ -45415,7 +45415,7 @@ function minimatch (p, pattern, options) { } // "" only matches "" - if (pattern.trim() === '') return p === '' + if (pattern.trim() === '') return p === ''; return new Minimatch(pattern, options).match(p) } @@ -45429,55 +45429,55 @@ function Minimatch (pattern, options) { throw new TypeError('glob pattern string required') } - if (!options) options = {} - pattern = pattern.trim() + if (!options) options = {}; + pattern = pattern.trim(); // windows support: need to use /, not \ if (path.sep !== '/') { pattern = pattern.split(path.sep).join('/') } - this.options = options - this.set = [] - this.pattern = pattern - this.regexp = null - this.negate = false - this.comment = false - this.empty = false + this.options = options; + this.set = []; + this.pattern = pattern; + this.regexp = null; + this.negate = false; + this.comment = false; + this.empty = false; // make the set of regexps etc. this.make() } -Minimatch.prototype.debug = function () {} +Minimatch.prototype.debug = function () {}; -Minimatch.prototype.make = make +Minimatch.prototype.make = make; function make () { // don't do it more than once. - if (this._made) return + if (this._made) return; - var pattern = this.pattern - var options = this.options + var pattern = this.pattern; + var options = this.options; // empty patterns and comments match nothing. if (!options.nocomment && pattern.charAt(0) === '#') { - this.comment = true + this.comment = true; return } if (!pattern) { - this.empty = true + this.empty = true; return } // step 1: figure out negation, etc. - this.parseNegate() + this.parseNegate(); // step 2: expand braces - var set = this.globSet = this.braceExpand() + var set = this.globSet = this.braceExpand(); - if (options.debug) this.debug = console.error + if (options.debug) this.debug = console.error; - this.debug(this.pattern, set) + this.debug(this.pattern, set); // step 3: now we have a set, so turn each one into a series of path-portion // matching patterns. @@ -45486,44 +45486,44 @@ function make () { // and will not contain any / characters set = this.globParts = set.map(function (s) { return s.split(slashSplit) - }) + }); - this.debug(this.pattern, set) + this.debug(this.pattern, set); // glob --> regexps set = set.map(function (s, si, set) { return s.map(this.parse, this) - }, this) + }, this); - this.debug(this.pattern, set) + this.debug(this.pattern, set); // filter out everything that didn't compile properly. set = set.filter(function (s) { return s.indexOf(false) === -1 - }) + }); - this.debug(this.pattern, set) + this.debug(this.pattern, set); this.set = set } -Minimatch.prototype.parseNegate = parseNegate +Minimatch.prototype.parseNegate = parseNegate; function parseNegate () { - var pattern = this.pattern - var negate = false - var options = this.options - var negateOffset = 0 + var pattern = this.pattern; + var negate = false; + var options = this.options; + var negateOffset = 0; - if (options.nonegate) return + if (options.nonegate) return; for (var i = 0, l = pattern.length ; i < l && pattern.charAt(i) === '!' ; i++) { - negate = !negate + negate = !negate; negateOffset++ } - if (negateOffset) this.pattern = pattern.substr(negateOffset) + if (negateOffset) this.pattern = pattern.substr(negateOffset); this.negate = negate } @@ -45539,9 +45539,9 @@ function parseNegate () { // a{b}c -> a{b}c minimatch.braceExpand = function (pattern, options) { return braceExpand(pattern, options) -} +}; -Minimatch.prototype.braceExpand = braceExpand +Minimatch.prototype.braceExpand = braceExpand; function braceExpand (pattern, options) { if (!options) { @@ -45553,7 +45553,7 @@ function braceExpand (pattern, options) { } pattern = typeof pattern === 'undefined' - ? this.pattern : pattern + ? this.pattern : pattern; if (typeof pattern === 'undefined') { throw new TypeError('undefined pattern') @@ -45579,36 +45579,36 @@ function braceExpand (pattern, options) { // when it is the *only* thing in a path portion. Otherwise, any series // of * is equivalent to a single *. Globstar behavior is enabled by // default, and can be disabled by setting options.noglobstar. -Minimatch.prototype.parse = parse -var SUBPARSE = {} +Minimatch.prototype.parse = parse; +var SUBPARSE = {}; function parse (pattern, isSub) { if (pattern.length > 1024 * 64) { throw new TypeError('pattern is too long') } - var options = this.options + var options = this.options; // shortcuts - if (!options.noglobstar && pattern === '**') return GLOBSTAR - if (pattern === '') return '' + if (!options.noglobstar && pattern === '**') return GLOBSTAR; + if (pattern === '') return ''; - var re = '' - var hasMagic = !!options.nocase - var escaping = false + var re = ''; + var hasMagic = !!options.nocase; + var escaping = false; // ? => one single character - var patternListStack = [] - var negativeLists = [] - var stateChar - var inClass = false - var reClassStart = -1 - var classStart = -1 + var patternListStack = []; + var negativeLists = []; + var stateChar; + var inClass = false; + var reClassStart = -1; + var classStart = -1; // . and .. never match anything that doesn't start with ., // even when options.dot is set. var patternStart = pattern.charAt(0) === '.' ? '' // anything // not (start or / followed by . or .. followed by / or end) : options.dot ? '(?!(?:^|\\\/)\\.{1,2}(?:$|\\\/))' - : '(?!\\.)' - var self = this + : '(?!\\.)'; + var self = this; function clearStateChar () { if (stateChar) { @@ -45616,18 +45616,18 @@ function parse (pattern, isSub) { // that wasn't consumed by this pass. switch (stateChar) { case '*': - re += star - hasMagic = true - break + re += star; + hasMagic = true; + break; case '?': - re += qmark - hasMagic = true - break + re += qmark; + hasMagic = true; + break; default: - re += '\\' + stateChar + re += '\\' + stateChar; break } - self.debug('clearStateChar %j %j', stateChar, re) + self.debug('clearStateChar %j %j', stateChar, re); stateChar = false } } @@ -45635,12 +45635,12 @@ function parse (pattern, isSub) { for (var i = 0, len = pattern.length, c ; (i < len) && (c = pattern.charAt(i)) ; i++) { - this.debug('%s\t%s %s %j', pattern, i, re, c) + this.debug('%s\t%s %s %j', pattern, i, re, c); // skip over any that are escaped. if (escaping && reSpecials[c]) { - re += '\\' + c - escaping = false + re += '\\' + c; + escaping = false; continue } @@ -45648,12 +45648,12 @@ function parse (pattern, isSub) { case '/': // completely not allowed, even escaped. // Should already be path-split by now. - return false + return false; case '\\': - clearStateChar() - escaping = true - continue + clearStateChar(); + escaping = true; + continue; // the various stateChar values // for the "extglob" stuff. @@ -45662,37 +45662,37 @@ function parse (pattern, isSub) { case '+': case '@': case '!': - this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c) + this.debug('%s\t%s %s %j <-- stateChar', pattern, i, re, c); // all of those are literals inside a class, except that // the glob [!a] means [^a] in regexp if (inClass) { - this.debug(' in class') - if (c === '!' && i === classStart + 1) c = '^' - re += c + this.debug(' in class'); + if (c === '!' && i === classStart + 1) c = '^'; + re += c; continue } // if we already have a stateChar, then it means // that there was something like ** or +? in there. // Handle the stateChar, then proceed with this one. - self.debug('call clearStateChar %j', stateChar) - clearStateChar() - stateChar = c + self.debug('call clearStateChar %j', stateChar); + clearStateChar(); + stateChar = c; // if extglob is disabled, then +(asdf|foo) isn't a thing. // just clear the statechar *now*, rather than even diving into // the patternList stuff. - if (options.noext) clearStateChar() - continue + if (options.noext) clearStateChar(); + continue; case '(': if (inClass) { - re += '(' + re += '('; continue } if (!stateChar) { - re += '\\(' + re += '\\('; continue } @@ -45702,57 +45702,57 @@ function parse (pattern, isSub) { reStart: re.length, open: plTypes[stateChar].open, close: plTypes[stateChar].close - }) + }); // negation is (?:(?!js)[^/]*) - re += stateChar === '!' ? '(?:(?!(?:' : '(?:' - this.debug('plType %j %j', stateChar, re) - stateChar = false - continue + re += stateChar === '!' ? '(?:(?!(?:' : '(?:'; + this.debug('plType %j %j', stateChar, re); + stateChar = false; + continue; case ')': if (inClass || !patternListStack.length) { - re += '\\)' + re += '\\)'; continue } - clearStateChar() - hasMagic = true - var pl = patternListStack.pop() + clearStateChar(); + hasMagic = true; + var pl = patternListStack.pop(); // negation is (?:(?!js)[^/]*) // The others are (?:<pattern>)<type> - re += pl.close + re += pl.close; if (pl.type === '!') { negativeLists.push(pl) } - pl.reEnd = re.length - continue + pl.reEnd = re.length; + continue; case '|': if (inClass || !patternListStack.length || escaping) { - re += '\\|' - escaping = false + re += '\\|'; + escaping = false; continue } - clearStateChar() - re += '|' - continue + clearStateChar(); + re += '|'; + continue; // these are mostly the same in regexp and glob case '[': // swallow any state-tracking char before the [ - clearStateChar() + clearStateChar(); if (inClass) { - re += '\\' + c + re += '\\' + c; continue } - inClass = true - classStart = i - reClassStart = re.length - re += c - continue + inClass = true; + classStart = i; + reClassStart = re.length; + re += c; + continue; case ']': // a right bracket shall lose its special @@ -45760,8 +45760,8 @@ function parse (pattern, isSub) { // a bracket expression if it occurs // first in the list. -- POSIX.2 2.8.3.2 if (i === classStart + 1 || !inClass) { - re += '\\' + c - escaping = false + re += '\\' + c; + escaping = false; continue } @@ -45775,28 +45775,28 @@ function parse (pattern, isSub) { // TODO: It would probably be faster to determine this // without a try/catch and a new RegExp, but it's tricky // to do safely. For now, this is safe and works. - var cs = pattern.substring(classStart + 1, i) + var cs = pattern.substring(classStart + 1, i); try { RegExp('[' + cs + ']') } catch (er) { // not a valid class! - var sp = this.parse(cs, SUBPARSE) - re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]' - hasMagic = hasMagic || sp[1] - inClass = false + var sp = this.parse(cs, SUBPARSE); + re = re.substr(0, reClassStart) + '\\[' + sp[0] + '\\]'; + hasMagic = hasMagic || sp[1]; + inClass = false; continue } } // finish up the class. - hasMagic = true - inClass = false - re += c - continue + hasMagic = true; + inClass = false; + re += c; + continue; default: // swallow any state char that wasn't consumed - clearStateChar() + clearStateChar(); if (escaping) { // no need @@ -45818,9 +45818,9 @@ function parse (pattern, isSub) { // this is a huge pita. We now have to re-walk // the contents of the would-be class to re-translate // any characters that were passed through as-is - cs = pattern.substr(classStart + 1) - sp = this.parse(cs, SUBPARSE) - re = re.substr(0, reClassStart) + '\\[' + sp[0] + cs = pattern.substr(classStart + 1); + sp = this.parse(cs, SUBPARSE); + re = re.substr(0, reClassStart) + '\\[' + sp[0]; hasMagic = hasMagic || sp[1] } @@ -45831,8 +45831,8 @@ function parse (pattern, isSub) { // Go through and escape them, taking care not to double-escape any // | chars that were already escaped. for (pl = patternListStack.pop(); pl; pl = patternListStack.pop()) { - var tail = re.slice(pl.reStart + pl.open.length) - this.debug('setting tail', re, pl) + var tail = re.slice(pl.reStart + pl.open.length); + this.debug('setting tail', re, pl); // maybe some even number of \, then maybe 1 \, followed by a | tail = tail.replace(/((?:\\{2}){0,64})(\\?)\|/g, function (_, $1, $2) { if (!$2) { @@ -45847,19 +45847,19 @@ function parse (pattern, isSub) { // // I am sorry that you have to see this. return $1 + $1 + $2 + '|' - }) + }); - this.debug('tail=%j\n %s', tail, tail, pl, re) + this.debug('tail=%j\n %s', tail, tail, pl, re); var t = pl.type === '*' ? star : pl.type === '?' ? qmark - : '\\' + pl.type + : '\\' + pl.type; - hasMagic = true + hasMagic = true; re = re.slice(0, pl.reStart) + t + '\\(' + tail } // handle trailing things that only matter at the very end. - clearStateChar() + clearStateChar(); if (escaping) { // trailing \\ re += '\\\\' @@ -45867,7 +45867,7 @@ function parse (pattern, isSub) { // only need to apply the nodot start if the re starts with // something that could conceivably capture a dot - var addPatternStart = false + var addPatternStart = false; switch (re.charAt(0)) { case '.': case '[': @@ -45880,30 +45880,30 @@ function parse (pattern, isSub) { // lookahead, has to look ALL the way ahead, to the end of // the pattern. for (var n = negativeLists.length - 1; n > -1; n--) { - var nl = negativeLists[n] + var nl = negativeLists[n]; - var nlBefore = re.slice(0, nl.reStart) - var nlFirst = re.slice(nl.reStart, nl.reEnd - 8) - var nlLast = re.slice(nl.reEnd - 8, nl.reEnd) - var nlAfter = re.slice(nl.reEnd) + var nlBefore = re.slice(0, nl.reStart); + var nlFirst = re.slice(nl.reStart, nl.reEnd - 8); + var nlLast = re.slice(nl.reEnd - 8, nl.reEnd); + var nlAfter = re.slice(nl.reEnd); - nlLast += nlAfter + nlLast += nlAfter; // Handle nested stuff like *(*.js|!(*.json)), where open parens // mean that we should *not* include the ) in the bit that is considered // "after" the negated section. - var openParensBefore = nlBefore.split('(').length - 1 - var cleanAfter = nlAfter + var openParensBefore = nlBefore.split('(').length - 1; + var cleanAfter = nlAfter; for (i = 0; i < openParensBefore; i++) { cleanAfter = cleanAfter.replace(/\)[+*?]?/, '') } - nlAfter = cleanAfter + nlAfter = cleanAfter; - var dollar = '' + var dollar = ''; if (nlAfter === '' && isSub !== SUBPARSE) { dollar = '$' } - var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast + var newRe = nlBefore + nlFirst + nlAfter + dollar + nlLast; re = newRe } @@ -45930,7 +45930,7 @@ function parse (pattern, isSub) { return globUnescape(pattern) } - var flags = options.nocase ? 'i' : '' + var flags = options.nocase ? 'i' : ''; try { var regExp = new RegExp('^' + re + '$', flags) } catch (er) { @@ -45941,19 +45941,19 @@ function parse (pattern, isSub) { return new RegExp('$.') } - regExp._glob = pattern - regExp._src = re + regExp._glob = pattern; + regExp._src = re; return regExp } minimatch.makeRe = function (pattern, options) { return new Minimatch(pattern, options || {}).makeRe() -} +}; -Minimatch.prototype.makeRe = makeRe +Minimatch.prototype.makeRe = makeRe; function makeRe () { - if (this.regexp || this.regexp === false) return this.regexp + if (this.regexp || this.regexp === false) return this.regexp; // at this point, this.set is a 2d array of partial // pattern strings, or "**". @@ -45961,18 +45961,18 @@ function makeRe () { // It's better to use .match(). This function shouldn't // be used, really, but it's pretty convenient sometimes, // when you just want to work with a regex. - var set = this.set + var set = this.set; if (!set.length) { - this.regexp = false + this.regexp = false; return this.regexp } - var options = this.options + var options = this.options; var twoStar = options.noglobstar ? star : options.dot ? twoStarDot - : twoStarNoDot - var flags = options.nocase ? 'i' : '' + : twoStarNoDot; + var flags = options.nocase ? 'i' : ''; var re = set.map(function (pattern) { return pattern.map(function (p) { @@ -45980,14 +45980,14 @@ function makeRe () { : (typeof p === 'string') ? regExpEscape(p) : p._src }).join('\\\/') - }).join('|') + }).join('|'); // must match entire pattern // ending in a * or ** will make it less strict. - re = '^(?:' + re + ')$' + re = '^(?:' + re + ')$'; // can match anything, as long as it's not this. - if (this.negate) re = '^(?!' + re + ').*$' + if (this.negate) re = '^(?!' + re + ').*$'; try { this.regexp = new RegExp(re, flags) @@ -45998,28 +45998,28 @@ function makeRe () { } minimatch.match = function (list, pattern, options) { - options = options || {} - var mm = new Minimatch(pattern, options) + options = options || {}; + var mm = new Minimatch(pattern, options); list = list.filter(function (f) { return mm.match(f) - }) + }); if (mm.options.nonull && !list.length) { list.push(pattern) } return list -} +}; -Minimatch.prototype.match = match +Minimatch.prototype.match = match; function match (f, partial) { - this.debug('match', f, this.pattern) + this.debug('match', f, this.pattern); // short-circuit in the case of busted things. // comments, etc. - if (this.comment) return false - if (this.empty) return f === '' + if (this.comment) return false; + if (this.empty) return f === ''; - if (f === '/' && partial) return true + if (f === '/' && partial) return true; - var options = this.options + var options = this.options; // windows: need to use /, not \ if (path.sep !== '/') { @@ -46027,41 +46027,41 @@ function match (f, partial) { } // treat the test path as a set of pathparts. - f = f.split(slashSplit) - this.debug(this.pattern, 'split', f) + f = f.split(slashSplit); + this.debug(this.pattern, 'split', f); // just ONE of the pattern sets in this.set needs to match // in order for it to be valid. If negating, then just one // match means that we have failed. // Either way, return on the first hit. - var set = this.set - this.debug(this.pattern, 'set', set) + var set = this.set; + this.debug(this.pattern, 'set', set); // Find the basename of the path by looking for the last non-empty segment - var filename - var i + var filename; + var i; for (i = f.length - 1; i >= 0; i--) { - filename = f[i] + filename = f[i]; if (filename) break } for (i = 0; i < set.length; i++) { - var pattern = set[i] - var file = f + var pattern = set[i]; + var file = f; if (options.matchBase && pattern.length === 1) { file = [filename] } - var hit = this.matchOne(file, pattern, partial) + var hit = this.matchOne(file, pattern, partial); if (hit) { - if (options.flipNegate) return true + if (options.flipNegate) return true; return !this.negate } } // didn't get any hits. this is success if it's a negative // pattern, failure otherwise. - if (options.flipNegate) return false + if (options.flipNegate) return false; return this.negate } @@ -46071,12 +46071,12 @@ function match (f, partial) { // out of pattern, then that's fine, as long as all // the parts match. Minimatch.prototype.matchOne = function (file, pattern, partial) { - var options = this.options + var options = this.options; this.debug('matchOne', - { 'this': this, file: file, pattern: pattern }) + { 'this': this, file: file, pattern: pattern }); - this.debug('matchOne', file.length, pattern.length) + this.debug('matchOne', file.length, pattern.length); for (var fi = 0, pi = 0, @@ -46084,18 +46084,18 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { pl = pattern.length ; (fi < fl) && (pi < pl) ; fi++, pi++) { - this.debug('matchOne loop') - var p = pattern[pi] - var f = file[fi] + this.debug('matchOne loop'); + var p = pattern[pi]; + var f = file[fi]; - this.debug(pattern, p, f) + this.debug(pattern, p, f); // should be impossible. // some invalid regexp stuff in the set. - if (p === false) return false + if (p === false) return false; if (p === GLOBSTAR) { - this.debug('GLOBSTAR', [pattern, p, f]) + this.debug('GLOBSTAR', [pattern, p, f]); // "**" // a/**/b/**/c would match the following: @@ -46119,10 +46119,10 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { // - matchOne(y/z/c, c) -> no // - matchOne(z/c, c) -> no // - matchOne(c, c) yes, hit - var fr = fi - var pr = pi + 1 + var fr = fi; + var pr = pi + 1; if (pr === pl) { - this.debug('** at the end') + this.debug('** at the end'); // a ** at the end will just swallow the rest. // We have found a match. // however, it will not swallow /.x, unless @@ -46138,13 +46138,13 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { // ok, let's see if we can swallow whatever we can. while (fr < fl) { - var swallowee = file[fr] + var swallowee = file[fr]; - this.debug('\nglobstar while', file, fr, pattern, pr, swallowee) + this.debug('\nglobstar while', file, fr, pattern, pr, swallowee); // XXX remove this slice. Just pass the start index. if (this.matchOne(file.slice(fr), pattern.slice(pr), partial)) { - this.debug('globstar found match!', fr, fl, swallowee) + this.debug('globstar found match!', fr, fl, swallowee); // found a match. return true } else { @@ -46152,12 +46152,12 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { // can only swallow ".foo" when explicitly asked. if (swallowee === '.' || swallowee === '..' || (!options.dot && swallowee.charAt(0) === '.')) { - this.debug('dot detected!', file, fr, pattern, pr) + this.debug('dot detected!', file, fr, pattern, pr); break } // ** swallows a segment, and continue. - this.debug('globstar swallow a segment, and continue') + this.debug('globstar swallow a segment, and continue'); fr++ } } @@ -46167,7 +46167,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { // If there's more *pattern* left, then if (partial) { // ran out of file - this.debug('\n>>> no match, partial?', file, fr, pattern, pr) + this.debug('\n>>> no match, partial?', file, fr, pattern, pr); if (fr === fl) return true } return false @@ -46176,7 +46176,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { // something other than ** // non-magic patterns just have to match exactly // patterns with magic have been turned into regexps. - var hit + var hit; if (typeof p === 'string') { if (options.nocase) { hit = f.toLowerCase() === p.toLowerCase() @@ -46185,7 +46185,7 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { } this.debug('string match', p, f, hit) } else { - hit = f.match(p) + hit = f.match(p); this.debug('pattern match', p, f, hit) } @@ -46218,13 +46218,13 @@ Minimatch.prototype.matchOne = function (file, pattern, partial) { // this is only acceptable if we're on the very last // empty segment of a file with a trailing slash. // a/* should match a/b/ - var emptyFileEnd = (fi === fl - 1) && (file[fi] === '') + var emptyFileEnd = (fi === fl - 1) && (file[fi] === ''); return emptyFileEnd } // should be unreachable. throw new Error('wtf?') -} +}; // replace stuff like \* with * function globUnescape (s) { @@ -46815,7 +46815,7 @@ function defaultClearTimeout () { } catch (e) { cachedClearTimeout = defaultClearTimeout; } -} ()) +} ()); function runTimeout(fun) { if (cachedSetTimeout === setTimeout) { //normal enviroments in sane situations @@ -46952,7 +46952,7 @@ process.emit = noop; process.prependListener = noop; process.prependOnceListener = noop; -process.listeners = function (name) { return [] } +process.listeners = function (name) { return [] }; process.binding = function (name) { throw new Error('process.binding is not supported'); @@ -47067,7 +47067,7 @@ process.umask = function() { return 0; }; if (tmp == previous + 1) { if (index != max) { previous = tmp; - continue; + } else { isStart = true; result.push(tmp + 1); @@ -50632,7 +50632,7 @@ function processTerm(item) { throw Error('Unknown term type: ' + item.type); } return item; -}; +} module.exports = function(pattern, flags) { var tree = parse(pattern, flags); @@ -50928,7 +50928,7 @@ module.exports = function(pattern, flags) { case null: switch (min) { case 0: - quantifier = '*' + quantifier = '*'; break; case 1: quantifier = '+'; @@ -52728,7 +52728,7 @@ function SourceMapConsumer(aSourceMap) { SourceMapConsumer.fromSourceMap = function(aSourceMap) { return BasicSourceMapConsumer.fromSourceMap(aSourceMap); -} +}; /** * The version of the source mapping spec that we are consuming. @@ -54063,7 +54063,7 @@ SourceMapGenerator.prototype._validateMapping = && aGenerated.line > 0 && aGenerated.column >= 0 && !aOriginal && !aSource && !aName) { // Case 1. - return; + } else if (aGenerated && 'line' in aGenerated && 'column' in aGenerated && aOriginal && 'line' in aOriginal && 'column' in aOriginal @@ -54071,7 +54071,7 @@ SourceMapGenerator.prototype._validateMapping = && aOriginal.line > 0 && aOriginal.column >= 0 && aSource) { // Cases 2 and 3. - return; + } else { throw new Error('Invalid mapping: ' + JSON.stringify({ @@ -54104,7 +54104,7 @@ SourceMapGenerator.prototype._serializeMappings = var mappings = this._mappings.toArray(); for (var i = 0, len = mappings.length; i < len; i++) { mapping = mappings[i]; - next = '' + next = ''; if (mapping.generatedLine !== previousGeneratedLine) { previousGeneratedColumn = 0; @@ -55151,7 +55151,7 @@ exports.WriteStream = WriteStream; if (typeof Object.create === 'function') { // implementation from standard node.js 'util' module module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor + ctor.super_ = superCtor; ctor.prototype = Object.create(superCtor.prototype, { constructor: { value: ctor, @@ -55164,10 +55164,10 @@ if (typeof Object.create === 'function') { } else { // old school shim for old browsers module.exports = function inherits(ctor, superCtor) { - ctor.super_ = superCtor - var TempCtor = function () {} - TempCtor.prototype = superCtor.prototype - ctor.prototype = new TempCtor() + ctor.super_ = superCtor; + var TempCtor = function () {}; + TempCtor.prototype = superCtor.prototype; + ctor.prototype = new TempCtor(); ctor.prototype.constructor = ctor } } diff --git a/static/js/novnc/vendor/browser-es-module-loader/src/browser-es-module-loader.js b/static/js/novnc/vendor/browser-es-module-loader/src/browser-es-module-loader.js index efae617..319caef 100755 --- a/static/js/novnc/vendor/browser-es-module-loader/src/browser-es-module-loader.js +++ b/static/js/novnc/vendor/browser-es-module-loader/src/browser-es-module-loader.js @@ -35,7 +35,7 @@ if (typeof document != 'undefined' && document.getElementsByTagName) { // throw so it still shows up in the console throw err; - } + }; var ready = function() { document.removeEventListener('DOMContentLoaded', ready, false ); @@ -63,7 +63,7 @@ if (typeof document != 'undefined' && document.getElementsByTagName) { } } } - } + }; // simple DOM ready if (document.readyState !== 'loading') @@ -105,10 +105,10 @@ function xhrFetch(url, resolve, reject) { var xhr = new XMLHttpRequest(); var load = function(source) { resolve(xhr.responseText); - } + }; var error = function() { reject(new Error('XHR error' + (xhr.status ? ' (' + xhr.status + (xhr.statusText ? ' ' + xhr.statusText : '') + ')' : '') + ' loading ' + url)); - } + }; xhr.onreadystatechange = function () { if (xhr.readyState === 4) { @@ -235,7 +235,7 @@ BrowserESModuleLoader.prototype[RegisterLoader.instantiate] = function(key, proc return new Promise(function(resolve, reject) { // anonymous module if (anonSources[key]) { - resolve(anonSources[key]) + resolve(anonSources[key]); anonSources[key] = undefined; } // otherwise we fetch diff --git a/static/js/novnc/vendor/pako/lib/utils/common.js b/static/js/novnc/vendor/pako/lib/utils/common.js index 576fd59..8959d9e 100755 --- a/static/js/novnc/vendor/pako/lib/utils/common.js +++ b/static/js/novnc/vendor/pako/lib/utils/common.js @@ -4,7 +4,7 @@ export function shrinkBuf (buf, size) { if (buf.subarray) { return buf.subarray(0, size); } buf.length = size; return buf; -}; +} export function arraySet (dest, src, src_offs, len, dest_offs) { diff --git a/static/js/novnc/vendor/pako/lib/zlib/inffast.js b/static/js/novnc/vendor/pako/lib/zlib/inffast.js index 889dcc7..b2b788a 100755 --- a/static/js/novnc/vendor/pako/lib/zlib/inffast.js +++ b/static/js/novnc/vendor/pako/lib/zlib/inffast.js @@ -277,7 +277,7 @@ export default function inflate_fast(strm, start) { } else if ((op & 64) === 0) { /* 2nd level distance code */ here = dcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dodist; + continue; } else { strm.msg = 'invalid distance code'; @@ -290,7 +290,7 @@ export default function inflate_fast(strm, start) { } else if ((op & 64) === 0) { /* 2nd level length code */ here = lcode[(here & 0xffff)/*here.val*/ + (hold & ((1 << op) - 1))]; - continue dolen; + continue; } else if (op & 32) { /* end-of-block */ //Tracevv((stderr, "inflate: end of block\n")); @@ -320,5 +320,5 @@ export default function inflate_fast(strm, start) { strm.avail_out = (_out < end ? 257 + (end - _out) : 257 - (_out - end)); state.hold = hold; state.bits = bits; - return; + }; diff --git a/static/js/plugins/flot/excanvas.min.js b/static/js/plugins/flot/excanvas.min.js deleted file mode 100755 index 12c74f7..0000000 --- a/static/js/plugins/flot/excanvas.min.js +++ /dev/null @@ -1 +0,0 @@ -if(!document.createElement("canvas").getContext){(function(){var z=Math;var K=z.round;var J=z.sin;var U=z.cos;var b=z.abs;var k=z.sqrt;var D=10;var F=D/2;function T(){return this.context_||(this.context_=new W(this))}var O=Array.prototype.slice;function G(i,j,m){var Z=O.call(arguments,2);return function(){return i.apply(j,Z.concat(O.call(arguments)))}}function AD(Z){return String(Z).replace(/&/g,"&").replace(/"/g,""")}function r(i){if(!i.namespaces.g_vml_){i.namespaces.add("g_vml_","urn:schemas-microsoft-com:vml","#default#VML")}if(!i.namespaces.g_o_){i.namespaces.add("g_o_","urn:schemas-microsoft-com:office:office","#default#VML")}if(!i.styleSheets.ex_canvas_){var Z=i.createStyleSheet();Z.owningElement.id="ex_canvas_";Z.cssText="canvas{display:inline-block;overflow:hidden;text-align:left;width:300px;height:150px}"}}r(document);var E={init:function(Z){if(/MSIE/.test(navigator.userAgent)&&!window.opera){var i=Z||document;i.createElement("canvas");i.attachEvent("onreadystatechange",G(this.init_,this,i))}},init_:function(m){var j=m.getElementsByTagName("canvas");for(var Z=0;Z<j.length;Z++){this.initElement(j[Z])}},initElement:function(i){if(!i.getContext){i.getContext=T;r(i.ownerDocument);i.innerHTML="";i.attachEvent("onpropertychange",S);i.attachEvent("onresize",w);var Z=i.attributes;if(Z.width&&Z.width.specified){i.style.width=Z.width.nodeValue+"px"}else{i.width=i.clientWidth}if(Z.height&&Z.height.specified){i.style.height=Z.height.nodeValue+"px"}else{i.height=i.clientHeight}}return i}};function S(i){var Z=i.srcElement;switch(i.propertyName){case"width":Z.getContext().clearRect();Z.style.width=Z.attributes.width.nodeValue+"px";Z.firstChild.style.width=Z.clientWidth+"px";break;case"height":Z.getContext().clearRect();Z.style.height=Z.attributes.height.nodeValue+"px";Z.firstChild.style.height=Z.clientHeight+"px";break}}function w(i){var Z=i.srcElement;if(Z.firstChild){Z.firstChild.style.width=Z.clientWidth+"px";Z.firstChild.style.height=Z.clientHeight+"px"}}E.init();var I=[];for(var AC=0;AC<16;AC++){for(var AB=0;AB<16;AB++){I[AC*16+AB]=AC.toString(16)+AB.toString(16)}}function V(){return[[1,0,0],[0,1,0],[0,0,1]]}function d(m,j){var i=V();for(var Z=0;Z<3;Z++){for(var AF=0;AF<3;AF++){var p=0;for(var AE=0;AE<3;AE++){p+=m[Z][AE]*j[AE][AF]}i[Z][AF]=p}}return i}function Q(i,Z){Z.fillStyle=i.fillStyle;Z.lineCap=i.lineCap;Z.lineJoin=i.lineJoin;Z.lineWidth=i.lineWidth;Z.miterLimit=i.miterLimit;Z.shadowBlur=i.shadowBlur;Z.shadowColor=i.shadowColor;Z.shadowOffsetX=i.shadowOffsetX;Z.shadowOffsetY=i.shadowOffsetY;Z.strokeStyle=i.strokeStyle;Z.globalAlpha=i.globalAlpha;Z.font=i.font;Z.textAlign=i.textAlign;Z.textBaseline=i.textBaseline;Z.arcScaleX_=i.arcScaleX_;Z.arcScaleY_=i.arcScaleY_;Z.lineScale_=i.lineScale_}var B={aliceblue:"#F0F8FF",antiquewhite:"#FAEBD7",aquamarine:"#7FFFD4",azure:"#F0FFFF",beige:"#F5F5DC",bisque:"#FFE4C4",black:"#000000",blanchedalmond:"#FFEBCD",blueviolet:"#8A2BE2",brown:"#A52A2A",burlywood:"#DEB887",cadetblue:"#5F9EA0",chartreuse:"#7FFF00",chocolate:"#D2691E",coral:"#FF7F50",cornflowerblue:"#6495ED",cornsilk:"#FFF8DC",crimson:"#DC143C",cyan:"#00FFFF",darkblue:"#00008B",darkcyan:"#008B8B",darkgoldenrod:"#B8860B",darkgray:"#A9A9A9",darkgreen:"#006400",darkgrey:"#A9A9A9",darkkhaki:"#BDB76B",darkmagenta:"#8B008B",darkolivegreen:"#556B2F",darkorange:"#FF8C00",darkorchid:"#9932CC",darkred:"#8B0000",darksalmon:"#E9967A",darkseagreen:"#8FBC8F",darkslateblue:"#483D8B",darkslategray:"#2F4F4F",darkslategrey:"#2F4F4F",darkturquoise:"#00CED1",darkviolet:"#9400D3",deeppink:"#FF1493",deepskyblue:"#00BFFF",dimgray:"#696969",dimgrey:"#696969",dodgerblue:"#1E90FF",firebrick:"#B22222",floralwhite:"#FFFAF0",forestgreen:"#228B22",gainsboro:"#DCDCDC",ghostwhite:"#F8F8FF",gold:"#FFD700",goldenrod:"#DAA520",grey:"#808080",greenyellow:"#ADFF2F",honeydew:"#F0FFF0",hotpink:"#FF69B4",indianred:"#CD5C5C",indigo:"#4B0082",ivory:"#FFFFF0",khaki:"#F0E68C",lavender:"#E6E6FA",lavenderblush:"#FFF0F5",lawngreen:"#7CFC00",lemonchiffon:"#FFFACD",lightblue:"#ADD8E6",lightcoral:"#F08080",lightcyan:"#E0FFFF",lightgoldenrodyellow:"#FAFAD2",lightgreen:"#90EE90",lightgrey:"#D3D3D3",lightpink:"#FFB6C1",lightsalmon:"#FFA07A",lightseagreen:"#20B2AA",lightskyblue:"#87CEFA",lightslategray:"#778899",lightslategrey:"#778899",lightsteelblue:"#B0C4DE",lightyellow:"#FFFFE0",limegreen:"#32CD32",linen:"#FAF0E6",magenta:"#FF00FF",mediumaquamarine:"#66CDAA",mediumblue:"#0000CD",mediumorchid:"#BA55D3",mediumpurple:"#9370DB",mediumseagreen:"#3CB371",mediumslateblue:"#7B68EE",mediumspringgreen:"#00FA9A",mediumturquoise:"#48D1CC",mediumvioletred:"#C71585",midnightblue:"#191970",mintcream:"#F5FFFA",mistyrose:"#FFE4E1",moccasin:"#FFE4B5",navajowhite:"#FFDEAD",oldlace:"#FDF5E6",olivedrab:"#6B8E23",orange:"#FFA500",orangered:"#FF4500",orchid:"#DA70D6",palegoldenrod:"#EEE8AA",palegreen:"#98FB98",paleturquoise:"#AFEEEE",palevioletred:"#DB7093",papayawhip:"#FFEFD5",peachpuff:"#FFDAB9",peru:"#CD853F",pink:"#FFC0CB",plum:"#DDA0DD",powderblue:"#B0E0E6",rosybrown:"#BC8F8F",royalblue:"#4169E1",saddlebrown:"#8B4513",salmon:"#FA8072",sandybrown:"#F4A460",seagreen:"#2E8B57",seashell:"#FFF5EE",sienna:"#A0522D",skyblue:"#87CEEB",slateblue:"#6A5ACD",slategray:"#708090",slategrey:"#708090",snow:"#FFFAFA",springgreen:"#00FF7F",steelblue:"#4682B4",tan:"#D2B48C",thistle:"#D8BFD8",tomato:"#FF6347",turquoise:"#40E0D0",violet:"#EE82EE",wheat:"#F5DEB3",whitesmoke:"#F5F5F5",yellowgreen:"#9ACD32"};function g(i){var m=i.indexOf("(",3);var Z=i.indexOf(")",m+1);var j=i.substring(m+1,Z).split(",");if(j.length==4&&i.substr(3,1)=="a"){alpha=Number(j[3])}else{j[3]=1}return j}function C(Z){return parseFloat(Z)/100}function N(i,j,Z){return Math.min(Z,Math.max(j,i))}function c(AF){var j,i,Z;h=parseFloat(AF[0])/360%360;if(h<0){h++}s=N(C(AF[1]),0,1);l=N(C(AF[2]),0,1);if(s==0){j=i=Z=l}else{var m=l<0.5?l*(1+s):l+s-l*s;var AE=2*l-m;j=A(AE,m,h+1/3);i=A(AE,m,h);Z=A(AE,m,h-1/3)}return"#"+I[Math.floor(j*255)]+I[Math.floor(i*255)]+I[Math.floor(Z*255)]}function A(i,Z,j){if(j<0){j++}if(j>1){j--}if(6*j<1){return i+(Z-i)*6*j}else{if(2*j<1){return Z}else{if(3*j<2){return i+(Z-i)*(2/3-j)*6}else{return i}}}}function Y(Z){var AE,p=1;Z=String(Z);if(Z.charAt(0)=="#"){AE=Z}else{if(/^rgb/.test(Z)){var m=g(Z);var AE="#",AF;for(var j=0;j<3;j++){if(m[j].indexOf("%")!=-1){AF=Math.floor(C(m[j])*255)}else{AF=Number(m[j])}AE+=I[N(AF,0,255)]}p=m[3]}else{if(/^hsl/.test(Z)){var m=g(Z);AE=c(m);p=m[3]}else{AE=B[Z]||Z}}}return{color:AE,alpha:p}}var L={style:"normal",variant:"normal",weight:"normal",size:10,family:"sans-serif"};var f={};function X(Z){if(f[Z]){return f[Z]}var m=document.createElement("div");var j=m.style;try{j.font=Z}catch(i){}return f[Z]={style:j.fontStyle||L.style,variant:j.fontVariant||L.variant,weight:j.fontWeight||L.weight,size:j.fontSize||L.size,family:j.fontFamily||L.family}}function P(j,i){var Z={};for(var AF in j){Z[AF]=j[AF]}var AE=parseFloat(i.currentStyle.fontSize),m=parseFloat(j.size);if(typeof j.size=="number"){Z.size=j.size}else{if(j.size.indexOf("px")!=-1){Z.size=m}else{if(j.size.indexOf("em")!=-1){Z.size=AE*m}else{if(j.size.indexOf("%")!=-1){Z.size=(AE/100)*m}else{if(j.size.indexOf("pt")!=-1){Z.size=m/0.75}else{Z.size=AE}}}}}Z.size*=0.981;return Z}function AA(Z){return Z.style+" "+Z.variant+" "+Z.weight+" "+Z.size+"px "+Z.family}function t(Z){switch(Z){case"butt":return"flat";case"round":return"round";case"square":default:return"square"}}function W(i){this.m_=V();this.mStack_=[];this.aStack_=[];this.currentPath_=[];this.strokeStyle="#000";this.fillStyle="#000";this.lineWidth=1;this.lineJoin="miter";this.lineCap="butt";this.miterLimit=D*1;this.globalAlpha=1;this.font="10px sans-serif";this.textAlign="left";this.textBaseline="alphabetic";this.canvas=i;var Z=i.ownerDocument.createElement("div");Z.style.width=i.clientWidth+"px";Z.style.height=i.clientHeight+"px";Z.style.overflow="hidden";Z.style.position="absolute";i.appendChild(Z);this.element_=Z;this.arcScaleX_=1;this.arcScaleY_=1;this.lineScale_=1}var M=W.prototype;M.clearRect=function(){if(this.textMeasureEl_){this.textMeasureEl_.removeNode(true);this.textMeasureEl_=null}this.element_.innerHTML=""};M.beginPath=function(){this.currentPath_=[]};M.moveTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"moveTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.lineTo=function(i,Z){var j=this.getCoords_(i,Z);this.currentPath_.push({type:"lineTo",x:j.x,y:j.y});this.currentX_=j.x;this.currentY_=j.y};M.bezierCurveTo=function(j,i,AI,AH,AG,AE){var Z=this.getCoords_(AG,AE);var AF=this.getCoords_(j,i);var m=this.getCoords_(AI,AH);e(this,AF,m,Z)};function e(Z,m,j,i){Z.currentPath_.push({type:"bezierCurveTo",cp1x:m.x,cp1y:m.y,cp2x:j.x,cp2y:j.y,x:i.x,y:i.y});Z.currentX_=i.x;Z.currentY_=i.y}M.quadraticCurveTo=function(AG,j,i,Z){var AF=this.getCoords_(AG,j);var AE=this.getCoords_(i,Z);var AH={x:this.currentX_+2/3*(AF.x-this.currentX_),y:this.currentY_+2/3*(AF.y-this.currentY_)};var m={x:AH.x+(AE.x-this.currentX_)/3,y:AH.y+(AE.y-this.currentY_)/3};e(this,AH,m,AE)};M.arc=function(AJ,AH,AI,AE,i,j){AI*=D;var AN=j?"at":"wa";var AK=AJ+U(AE)*AI-F;var AM=AH+J(AE)*AI-F;var Z=AJ+U(i)*AI-F;var AL=AH+J(i)*AI-F;if(AK==Z&&!j){AK+=0.125}var m=this.getCoords_(AJ,AH);var AG=this.getCoords_(AK,AM);var AF=this.getCoords_(Z,AL);this.currentPath_.push({type:AN,x:m.x,y:m.y,radius:AI,xStart:AG.x,yStart:AG.y,xEnd:AF.x,yEnd:AF.y})};M.rect=function(j,i,Z,m){this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath()};M.strokeRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.stroke();this.currentPath_=p};M.fillRect=function(j,i,Z,m){var p=this.currentPath_;this.beginPath();this.moveTo(j,i);this.lineTo(j+Z,i);this.lineTo(j+Z,i+m);this.lineTo(j,i+m);this.closePath();this.fill();this.currentPath_=p};M.createLinearGradient=function(i,m,Z,j){var p=new v("gradient");p.x0_=i;p.y0_=m;p.x1_=Z;p.y1_=j;return p};M.createRadialGradient=function(m,AE,j,i,p,Z){var AF=new v("gradientradial");AF.x0_=m;AF.y0_=AE;AF.r0_=j;AF.x1_=i;AF.y1_=p;AF.r1_=Z;return AF};M.drawImage=function(AO,j){var AH,AF,AJ,AV,AM,AK,AQ,AX;var AI=AO.runtimeStyle.width;var AN=AO.runtimeStyle.height;AO.runtimeStyle.width="auto";AO.runtimeStyle.height="auto";var AG=AO.width;var AT=AO.height;AO.runtimeStyle.width=AI;AO.runtimeStyle.height=AN;if(arguments.length==3){AH=arguments[1];AF=arguments[2];AM=AK=0;AQ=AJ=AG;AX=AV=AT}else{if(arguments.length==5){AH=arguments[1];AF=arguments[2];AJ=arguments[3];AV=arguments[4];AM=AK=0;AQ=AG;AX=AT}else{if(arguments.length==9){AM=arguments[1];AK=arguments[2];AQ=arguments[3];AX=arguments[4];AH=arguments[5];AF=arguments[6];AJ=arguments[7];AV=arguments[8]}else{throw Error("Invalid number of arguments")}}}var AW=this.getCoords_(AH,AF);var m=AQ/2;var i=AX/2;var AU=[];var Z=10;var AE=10;AU.push(" <g_vml_:group",' coordsize="',D*Z,",",D*AE,'"',' coordorigin="0,0"',' style="width:',Z,"px;height:",AE,"px;position:absolute;");if(this.m_[0][0]!=1||this.m_[0][1]||this.m_[1][1]!=1||this.m_[1][0]){var p=[];p.push("M11=",this.m_[0][0],",","M12=",this.m_[1][0],",","M21=",this.m_[0][1],",","M22=",this.m_[1][1],",","Dx=",K(AW.x/D),",","Dy=",K(AW.y/D),"");var AS=AW;var AR=this.getCoords_(AH+AJ,AF);var AP=this.getCoords_(AH,AF+AV);var AL=this.getCoords_(AH+AJ,AF+AV);AS.x=z.max(AS.x,AR.x,AP.x,AL.x);AS.y=z.max(AS.y,AR.y,AP.y,AL.y);AU.push("padding:0 ",K(AS.x/D),"px ",K(AS.y/D),"px 0;filter:progid:DXImageTransform.Microsoft.Matrix(",p.join(""),", sizingmethod='clip');")}else{AU.push("top:",K(AW.y/D),"px;left:",K(AW.x/D),"px;")}AU.push(' ">','<g_vml_:image src="',AO.src,'"',' style="width:',D*AJ,"px;"," height:",D*AV,'px"',' cropleft="',AM/AG,'"',' croptop="',AK/AT,'"',' cropright="',(AG-AM-AQ)/AG,'"',' cropbottom="',(AT-AK-AX)/AT,'"'," />","</g_vml_:group>");this.element_.insertAdjacentHTML("BeforeEnd",AU.join(""))};M.stroke=function(AM){var m=10;var AN=10;var AE=5000;var AG={x:null,y:null};var AL={x:null,y:null};for(var AH=0;AH<this.currentPath_.length;AH+=AE){var AK=[];var AF=false;AK.push("<g_vml_:shape",' filled="',!!AM,'"',' style="position:absolute;width:',m,"px;height:",AN,'px;"',' coordorigin="0,0"',' coordsize="',D*m,",",D*AN,'"',' stroked="',!AM,'"',' path="');var AO=false;for(var AI=AH;AI<Math.min(AH+AE,this.currentPath_.length);AI++){if(AI%AE==0&&AI>0){AK.push(" m ",K(this.currentPath_[AI-1].x),",",K(this.currentPath_[AI-1].y))}var Z=this.currentPath_[AI];var AJ;switch(Z.type){case"moveTo":AJ=Z;AK.push(" m ",K(Z.x),",",K(Z.y));break;case"lineTo":AK.push(" l ",K(Z.x),",",K(Z.y));break;case"close":AK.push(" x ");Z=null;break;case"bezierCurveTo":AK.push(" c ",K(Z.cp1x),",",K(Z.cp1y),",",K(Z.cp2x),",",K(Z.cp2y),",",K(Z.x),",",K(Z.y));break;case"at":case"wa":AK.push(" ",Z.type," ",K(Z.x-this.arcScaleX_*Z.radius),",",K(Z.y-this.arcScaleY_*Z.radius)," ",K(Z.x+this.arcScaleX_*Z.radius),",",K(Z.y+this.arcScaleY_*Z.radius)," ",K(Z.xStart),",",K(Z.yStart)," ",K(Z.xEnd),",",K(Z.yEnd));break}if(Z){if(AG.x==null||Z.x<AG.x){AG.x=Z.x}if(AL.x==null||Z.x>AL.x){AL.x=Z.x}if(AG.y==null||Z.y<AG.y){AG.y=Z.y}if(AL.y==null||Z.y>AL.y){AL.y=Z.y}}}AK.push(' ">');if(!AM){R(this,AK)}else{a(this,AK,AG,AL)}AK.push("</g_vml_:shape>");this.element_.insertAdjacentHTML("beforeEnd",AK.join(""))}};function R(j,AE){var i=Y(j.strokeStyle);var m=i.color;var p=i.alpha*j.globalAlpha;var Z=j.lineScale_*j.lineWidth;if(Z<1){p*=Z}AE.push("<g_vml_:stroke",' opacity="',p,'"',' joinstyle="',j.lineJoin,'"',' miterlimit="',j.miterLimit,'"',' endcap="',t(j.lineCap),'"',' weight="',Z,'px"',' color="',m,'" />')}function a(AO,AG,Ah,AP){var AH=AO.fillStyle;var AY=AO.arcScaleX_;var AX=AO.arcScaleY_;var Z=AP.x-Ah.x;var m=AP.y-Ah.y;if(AH instanceof v){var AL=0;var Ac={x:0,y:0};var AU=0;var AK=1;if(AH.type_=="gradient"){var AJ=AH.x0_/AY;var j=AH.y0_/AX;var AI=AH.x1_/AY;var Aj=AH.y1_/AX;var Ag=AO.getCoords_(AJ,j);var Af=AO.getCoords_(AI,Aj);var AE=Af.x-Ag.x;var p=Af.y-Ag.y;AL=Math.atan2(AE,p)*180/Math.PI;if(AL<0){AL+=360}if(AL<0.000001){AL=0}}else{var Ag=AO.getCoords_(AH.x0_,AH.y0_);Ac={x:(Ag.x-Ah.x)/Z,y:(Ag.y-Ah.y)/m};Z/=AY*D;m/=AX*D;var Aa=z.max(Z,m);AU=2*AH.r0_/Aa;AK=2*AH.r1_/Aa-AU}var AS=AH.colors_;AS.sort(function(Ak,i){return Ak.offset-i.offset});var AN=AS.length;var AR=AS[0].color;var AQ=AS[AN-1].color;var AW=AS[0].alpha*AO.globalAlpha;var AV=AS[AN-1].alpha*AO.globalAlpha;var Ab=[];for(var Ae=0;Ae<AN;Ae++){var AM=AS[Ae];Ab.push(AM.offset*AK+AU+" "+AM.color)}AG.push('<g_vml_:fill type="',AH.type_,'"',' method="none" focus="100%"',' color="',AR,'"',' color2="',AQ,'"',' colors="',Ab.join(","),'"',' opacity="',AV,'"',' g_o_:opacity2="',AW,'"',' angle="',AL,'"',' focusposition="',Ac.x,",",Ac.y,'" />')}else{if(AH instanceof u){if(Z&&m){var AF=-Ah.x;var AZ=-Ah.y;AG.push("<g_vml_:fill",' position="',AF/Z*AY*AY,",",AZ/m*AX*AX,'"',' type="tile"',' src="',AH.src_,'" />')}}else{var Ai=Y(AO.fillStyle);var AT=Ai.color;var Ad=Ai.alpha*AO.globalAlpha;AG.push('<g_vml_:fill color="',AT,'" opacity="',Ad,'" />')}}}M.fill=function(){this.stroke(true)};M.closePath=function(){this.currentPath_.push({type:"close"})};M.getCoords_=function(j,i){var Z=this.m_;return{x:D*(j*Z[0][0]+i*Z[1][0]+Z[2][0])-F,y:D*(j*Z[0][1]+i*Z[1][1]+Z[2][1])-F}};M.save=function(){var Z={};Q(this,Z);this.aStack_.push(Z);this.mStack_.push(this.m_);this.m_=d(V(),this.m_)};M.restore=function(){if(this.aStack_.length){Q(this.aStack_.pop(),this);this.m_=this.mStack_.pop()}};function H(Z){return isFinite(Z[0][0])&&isFinite(Z[0][1])&&isFinite(Z[1][0])&&isFinite(Z[1][1])&&isFinite(Z[2][0])&&isFinite(Z[2][1])}function y(i,Z,j){if(!H(Z)){return }i.m_=Z;if(j){var p=Z[0][0]*Z[1][1]-Z[0][1]*Z[1][0];i.lineScale_=k(b(p))}}M.translate=function(j,i){var Z=[[1,0,0],[0,1,0],[j,i,1]];y(this,d(Z,this.m_),false)};M.rotate=function(i){var m=U(i);var j=J(i);var Z=[[m,j,0],[-j,m,0],[0,0,1]];y(this,d(Z,this.m_),false)};M.scale=function(j,i){this.arcScaleX_*=j;this.arcScaleY_*=i;var Z=[[j,0,0],[0,i,0],[0,0,1]];y(this,d(Z,this.m_),true)};M.transform=function(p,m,AF,AE,i,Z){var j=[[p,m,0],[AF,AE,0],[i,Z,1]];y(this,d(j,this.m_),true)};M.setTransform=function(AE,p,AG,AF,j,i){var Z=[[AE,p,0],[AG,AF,0],[j,i,1]];y(this,Z,true)};M.drawText_=function(AK,AI,AH,AN,AG){var AM=this.m_,AQ=1000,i=0,AP=AQ,AF={x:0,y:0},AE=[];var Z=P(X(this.font),this.element_);var j=AA(Z);var AR=this.element_.currentStyle;var p=this.textAlign.toLowerCase();switch(p){case"left":case"center":case"right":break;case"end":p=AR.direction=="ltr"?"right":"left";break;case"start":p=AR.direction=="rtl"?"right":"left";break;default:p="left"}switch(this.textBaseline){case"hanging":case"top":AF.y=Z.size/1.75;break;case"middle":break;default:case null:case"alphabetic":case"ideographic":case"bottom":AF.y=-Z.size/2.25;break}switch(p){case"right":i=AQ;AP=0.05;break;case"center":i=AP=AQ/2;break}var AO=this.getCoords_(AI+AF.x,AH+AF.y);AE.push('<g_vml_:line from="',-i,' 0" to="',AP,' 0.05" ',' coordsize="100 100" coordorigin="0 0"',' filled="',!AG,'" stroked="',!!AG,'" style="position:absolute;width:1px;height:1px;">');if(AG){R(this,AE)}else{a(this,AE,{x:-i,y:0},{x:AP,y:Z.size})}var AL=AM[0][0].toFixed(3)+","+AM[1][0].toFixed(3)+","+AM[0][1].toFixed(3)+","+AM[1][1].toFixed(3)+",0,0";var AJ=K(AO.x/D)+","+K(AO.y/D);AE.push('<g_vml_:skew on="t" matrix="',AL,'" ',' offset="',AJ,'" origin="',i,' 0" />','<g_vml_:path textpathok="true" />','<g_vml_:textpath on="true" string="',AD(AK),'" style="v-text-align:',p,";font:",AD(j),'" /></g_vml_:line>');this.element_.insertAdjacentHTML("beforeEnd",AE.join(""))};M.fillText=function(j,Z,m,i){this.drawText_(j,Z,m,i,false)};M.strokeText=function(j,Z,m,i){this.drawText_(j,Z,m,i,true)};M.measureText=function(j){if(!this.textMeasureEl_){var Z='<span style="position:absolute;top:-20000px;left:0;padding:0;margin:0;border:none;white-space:pre;"></span>';this.element_.insertAdjacentHTML("beforeEnd",Z);this.textMeasureEl_=this.element_.lastChild}var i=this.element_.ownerDocument;this.textMeasureEl_.innerHTML="";this.textMeasureEl_.style.font=this.font;this.textMeasureEl_.appendChild(i.createTextNode(j));return{width:this.textMeasureEl_.offsetWidth}};M.clip=function(){};M.arcTo=function(){};M.createPattern=function(i,Z){return new u(i,Z)};function v(Z){this.type_=Z;this.x0_=0;this.y0_=0;this.r0_=0;this.x1_=0;this.y1_=0;this.r1_=0;this.colors_=[]}v.prototype.addColorStop=function(i,Z){Z=Y(Z);this.colors_.push({offset:i,color:Z.color,alpha:Z.alpha})};function u(i,Z){q(i);switch(Z){case"repeat":case null:case"":this.repetition_="repeat";break;case"repeat-x":case"repeat-y":case"no-repeat":this.repetition_=Z;break;default:n("SYNTAX_ERR")}this.src_=i.src;this.width_=i.width;this.height_=i.height}function n(Z){throw new o(Z)}function q(Z){if(!Z||Z.nodeType!=1||Z.tagName!="IMG"){n("TYPE_MISMATCH_ERR")}if(Z.readyState!="complete"){n("INVALID_STATE_ERR")}}function o(Z){this.code=this[Z];this.message=Z+": DOM Exception "+this.code}var x=o.prototype=new Error;x.INDEX_SIZE_ERR=1;x.DOMSTRING_SIZE_ERR=2;x.HIERARCHY_REQUEST_ERR=3;x.WRONG_DOCUMENT_ERR=4;x.INVALID_CHARACTER_ERR=5;x.NO_DATA_ALLOWED_ERR=6;x.NO_MODIFICATION_ALLOWED_ERR=7;x.NOT_FOUND_ERR=8;x.NOT_SUPPORTED_ERR=9;x.INUSE_ATTRIBUTE_ERR=10;x.INVALID_STATE_ERR=11;x.SYNTAX_ERR=12;x.INVALID_MODIFICATION_ERR=13;x.NAMESPACE_ERR=14;x.INVALID_ACCESS_ERR=15;x.VALIDATION_ERR=16;x.TYPE_MISMATCH_ERR=17;G_vmlCanvasManager=E;CanvasRenderingContext2D=W;CanvasGradient=v;CanvasPattern=u;DOMException=o})()}; \ No newline at end of file diff --git a/static/js/plugins/flot/flot-data.js b/static/js/plugins/flot/flot-data.js deleted file mode 100755 index b6d68fc..0000000 --- a/static/js/plugins/flot/flot-data.js +++ /dev/null @@ -1,1244 +0,0 @@ -// Flot Charts sample data for SB Admin template - -// Flot Line Chart with Tooltips -$(document).ready(function() { - console.log("document ready"); - var offset = 0; - plot(); - - function plot() { - var sin = [], - cos = []; - for (var i = 0; i < 12; i += 0.2) { - sin.push([i, Math.sin(i + offset)]); - cos.push([i, Math.cos(i + offset)]); - } - - var options = { - series: { - lines: { - show: true - }, - points: { - show: true - } - }, - grid: { - hoverable: true //IMPORTANT! this is needed for tooltip to work - }, - yaxis: { - min: -1.2, - max: 1.2 - }, - tooltip: true, - tooltipOpts: { - content: "'%s' of %x.1 is %y.4", - shifts: { - x: -60, - y: 25 - } - } - }; - - var plotObj = $.plot($("#flot-line-chart"), [{ - data: sin, - label: "sin(x)" - }, { - data: cos, - label: "cos(x)" - }], - options); - } -}); - -// Flot Pie Chart with Tooltips -$(function() { - - var data = [{ - label: "Series 0", - data: 1 - }, { - label: "Series 1", - data: 3 - }, { - label: "Series 2", - data: 9 - }, { - label: "Series 3", - data: 20 - }]; - - var plotObj = $.plot($("#flot-pie-chart"), data, { - series: { - pie: { - show: true - } - }, - grid: { - hoverable: true - }, - tooltip: true, - tooltipOpts: { - content: "%p.0%, %s", // show percentages, rounding to 2 decimal places - shifts: { - x: 20, - y: 0 - }, - defaultTheme: false - } - }); - -}); - -// Flot Line Charts - Multiple Axes - With Data -$(function() { - var oilprices = [ - [1167692400000, 61.05], - [1167778800000, 58.32], - [1167865200000, 57.35], - [1167951600000, 56.31], - [1168210800000, 55.55], - [1168297200000, 55.64], - [1168383600000, 54.02], - [1168470000000, 51.88], - [1168556400000, 52.99], - [1168815600000, 52.99], - [1168902000000, 51.21], - [1168988400000, 52.24], - [1169074800000, 50.48], - [1169161200000, 51.99], - [1169420400000, 51.13], - [1169506800000, 55.04], - [1169593200000, 55.37], - [1169679600000, 54.23], - [1169766000000, 55.42], - [1170025200000, 54.01], - [1170111600000, 56.97], - [1170198000000, 58.14], - [1170284400000, 58.14], - [1170370800000, 59.02], - [1170630000000, 58.74], - [1170716400000, 58.88], - [1170802800000, 57.71], - [1170889200000, 59.71], - [1170975600000, 59.89], - [1171234800000, 57.81], - [1171321200000, 59.06], - [1171407600000, 58.00], - [1171494000000, 57.99], - [1171580400000, 59.39], - [1171839600000, 59.39], - [1171926000000, 58.07], - [1172012400000, 60.07], - [1172098800000, 61.14], - [1172444400000, 61.39], - [1172530800000, 61.46], - [1172617200000, 61.79], - [1172703600000, 62.00], - [1172790000000, 60.07], - [1173135600000, 60.69], - [1173222000000, 61.82], - [1173308400000, 60.05], - [1173654000000, 58.91], - [1173740400000, 57.93], - [1173826800000, 58.16], - [1173913200000, 57.55], - [1173999600000, 57.11], - [1174258800000, 56.59], - [1174345200000, 59.61], - [1174518000000, 61.69], - [1174604400000, 62.28], - [1174860000000, 62.91], - [1174946400000, 62.93], - [1175032800000, 64.03], - [1175119200000, 66.03], - [1175205600000, 65.87], - [1175464800000, 64.64], - [1175637600000, 64.38], - [1175724000000, 64.28], - [1175810400000, 64.28], - [1176069600000, 61.51], - [1176156000000, 61.89], - [1176242400000, 62.01], - [1176328800000, 63.85], - [1176415200000, 63.63], - [1176674400000, 63.61], - [1176760800000, 63.10], - [1176847200000, 63.13], - [1176933600000, 61.83], - [1177020000000, 63.38], - [1177279200000, 64.58], - [1177452000000, 65.84], - [1177538400000, 65.06], - [1177624800000, 66.46], - [1177884000000, 64.40], - [1178056800000, 63.68], - [1178143200000, 63.19], - [1178229600000, 61.93], - [1178488800000, 61.47], - [1178575200000, 61.55], - [1178748000000, 61.81], - [1178834400000, 62.37], - [1179093600000, 62.46], - [1179180000000, 63.17], - [1179266400000, 62.55], - [1179352800000, 64.94], - [1179698400000, 66.27], - [1179784800000, 65.50], - [1179871200000, 65.77], - [1179957600000, 64.18], - [1180044000000, 65.20], - [1180389600000, 63.15], - [1180476000000, 63.49], - [1180562400000, 65.08], - [1180908000000, 66.30], - [1180994400000, 65.96], - [1181167200000, 66.93], - [1181253600000, 65.98], - [1181599200000, 65.35], - [1181685600000, 66.26], - [1181858400000, 68.00], - [1182117600000, 69.09], - [1182204000000, 69.10], - [1182290400000, 68.19], - [1182376800000, 68.19], - [1182463200000, 69.14], - [1182722400000, 68.19], - [1182808800000, 67.77], - [1182895200000, 68.97], - [1182981600000, 69.57], - [1183068000000, 70.68], - [1183327200000, 71.09], - [1183413600000, 70.92], - [1183586400000, 71.81], - [1183672800000, 72.81], - [1183932000000, 72.19], - [1184018400000, 72.56], - [1184191200000, 72.50], - [1184277600000, 74.15], - [1184623200000, 75.05], - [1184796000000, 75.92], - [1184882400000, 75.57], - [1185141600000, 74.89], - [1185228000000, 73.56], - [1185314400000, 75.57], - [1185400800000, 74.95], - [1185487200000, 76.83], - [1185832800000, 78.21], - [1185919200000, 76.53], - [1186005600000, 76.86], - [1186092000000, 76.00], - [1186437600000, 71.59], - [1186696800000, 71.47], - [1186956000000, 71.62], - [1187042400000, 71.00], - [1187301600000, 71.98], - [1187560800000, 71.12], - [1187647200000, 69.47], - [1187733600000, 69.26], - [1187820000000, 69.83], - [1187906400000, 71.09], - [1188165600000, 71.73], - [1188338400000, 73.36], - [1188511200000, 74.04], - [1188856800000, 76.30], - [1189116000000, 77.49], - [1189461600000, 78.23], - [1189548000000, 79.91], - [1189634400000, 80.09], - [1189720800000, 79.10], - [1189980000000, 80.57], - [1190066400000, 81.93], - [1190239200000, 83.32], - [1190325600000, 81.62], - [1190584800000, 80.95], - [1190671200000, 79.53], - [1190757600000, 80.30], - [1190844000000, 82.88], - [1190930400000, 81.66], - [1191189600000, 80.24], - [1191276000000, 80.05], - [1191362400000, 79.94], - [1191448800000, 81.44], - [1191535200000, 81.22], - [1191794400000, 79.02], - [1191880800000, 80.26], - [1191967200000, 80.30], - [1192053600000, 83.08], - [1192140000000, 83.69], - [1192399200000, 86.13], - [1192485600000, 87.61], - [1192572000000, 87.40], - [1192658400000, 89.47], - [1192744800000, 88.60], - [1193004000000, 87.56], - [1193090400000, 87.56], - [1193176800000, 87.10], - [1193263200000, 91.86], - [1193612400000, 93.53], - [1193698800000, 94.53], - [1193871600000, 95.93], - [1194217200000, 93.98], - [1194303600000, 96.37], - [1194476400000, 95.46], - [1194562800000, 96.32], - [1195081200000, 93.43], - [1195167600000, 95.10], - [1195426800000, 94.64], - [1195513200000, 95.10], - [1196031600000, 97.70], - [1196118000000, 94.42], - [1196204400000, 90.62], - [1196290800000, 91.01], - [1196377200000, 88.71], - [1196636400000, 88.32], - [1196809200000, 90.23], - [1196982000000, 88.28], - [1197241200000, 87.86], - [1197327600000, 90.02], - [1197414000000, 92.25], - [1197586800000, 90.63], - [1197846000000, 90.63], - [1197932400000, 90.49], - [1198018800000, 91.24], - [1198105200000, 91.06], - [1198191600000, 90.49], - [1198710000000, 96.62], - [1198796400000, 96.00], - [1199142000000, 99.62], - [1199314800000, 99.18], - [1199401200000, 95.09], - [1199660400000, 96.33], - [1199833200000, 95.67], - [1200351600000, 91.90], - [1200438000000, 90.84], - [1200524400000, 90.13], - [1200610800000, 90.57], - [1200956400000, 89.21], - [1201042800000, 86.99], - [1201129200000, 89.85], - [1201474800000, 90.99], - [1201561200000, 91.64], - [1201647600000, 92.33], - [1201734000000, 91.75], - [1202079600000, 90.02], - [1202166000000, 88.41], - [1202252400000, 87.14], - [1202338800000, 88.11], - [1202425200000, 91.77], - [1202770800000, 92.78], - [1202857200000, 93.27], - [1202943600000, 95.46], - [1203030000000, 95.46], - [1203289200000, 101.74], - [1203462000000, 98.81], - [1203894000000, 100.88], - [1204066800000, 99.64], - [1204153200000, 102.59], - [1204239600000, 101.84], - [1204498800000, 99.52], - [1204585200000, 99.52], - [1204671600000, 104.52], - [1204758000000, 105.47], - [1204844400000, 105.15], - [1205103600000, 108.75], - [1205276400000, 109.92], - [1205362800000, 110.33], - [1205449200000, 110.21], - [1205708400000, 105.68], - [1205967600000, 101.84], - [1206313200000, 100.86], - [1206399600000, 101.22], - [1206486000000, 105.90], - [1206572400000, 107.58], - [1206658800000, 105.62], - [1206914400000, 101.58], - [1207000800000, 100.98], - [1207173600000, 103.83], - [1207260000000, 106.23], - [1207605600000, 108.50], - [1207778400000, 110.11], - [1207864800000, 110.14], - [1208210400000, 113.79], - [1208296800000, 114.93], - [1208383200000, 114.86], - [1208728800000, 117.48], - [1208815200000, 118.30], - [1208988000000, 116.06], - [1209074400000, 118.52], - [1209333600000, 118.75], - [1209420000000, 113.46], - [1209592800000, 112.52], - [1210024800000, 121.84], - [1210111200000, 123.53], - [1210197600000, 123.69], - [1210543200000, 124.23], - [1210629600000, 125.80], - [1210716000000, 126.29], - [1211148000000, 127.05], - [1211320800000, 129.07], - [1211493600000, 132.19], - [1211839200000, 128.85], - [1212357600000, 127.76], - [1212703200000, 138.54], - [1212962400000, 136.80], - [1213135200000, 136.38], - [1213308000000, 134.86], - [1213653600000, 134.01], - [1213740000000, 136.68], - [1213912800000, 135.65], - [1214172000000, 134.62], - [1214258400000, 134.62], - [1214344800000, 134.62], - [1214431200000, 139.64], - [1214517600000, 140.21], - [1214776800000, 140.00], - [1214863200000, 140.97], - [1214949600000, 143.57], - [1215036000000, 145.29], - [1215381600000, 141.37], - [1215468000000, 136.04], - [1215727200000, 146.40], - [1215986400000, 145.18], - [1216072800000, 138.74], - [1216159200000, 134.60], - [1216245600000, 129.29], - [1216332000000, 130.65], - [1216677600000, 127.95], - [1216850400000, 127.95], - [1217282400000, 122.19], - [1217455200000, 124.08], - [1217541600000, 125.10], - [1217800800000, 121.41], - [1217887200000, 119.17], - [1217973600000, 118.58], - [1218060000000, 120.02], - [1218405600000, 114.45], - [1218492000000, 113.01], - [1218578400000, 116.00], - [1218751200000, 113.77], - [1219010400000, 112.87], - [1219096800000, 114.53], - [1219269600000, 114.98], - [1219356000000, 114.98], - [1219701600000, 116.27], - [1219788000000, 118.15], - [1219874400000, 115.59], - [1219960800000, 115.46], - [1220306400000, 109.71], - [1220392800000, 109.35], - [1220565600000, 106.23], - [1220824800000, 106.34] - ]; - var exchangerates = [ - [1167606000000, 0.7580], - [1167692400000, 0.7580], - [1167778800000, 0.75470], - [1167865200000, 0.75490], - [1167951600000, 0.76130], - [1168038000000, 0.76550], - [1168124400000, 0.76930], - [1168210800000, 0.76940], - [1168297200000, 0.76880], - [1168383600000, 0.76780], - [1168470000000, 0.77080], - [1168556400000, 0.77270], - [1168642800000, 0.77490], - [1168729200000, 0.77410], - [1168815600000, 0.77410], - [1168902000000, 0.77320], - [1168988400000, 0.77270], - [1169074800000, 0.77370], - [1169161200000, 0.77240], - [1169247600000, 0.77120], - [1169334000000, 0.7720], - [1169420400000, 0.77210], - [1169506800000, 0.77170], - [1169593200000, 0.77040], - [1169679600000, 0.7690], - [1169766000000, 0.77110], - [1169852400000, 0.7740], - [1169938800000, 0.77450], - [1170025200000, 0.77450], - [1170111600000, 0.7740], - [1170198000000, 0.77160], - [1170284400000, 0.77130], - [1170370800000, 0.76780], - [1170457200000, 0.76880], - [1170543600000, 0.77180], - [1170630000000, 0.77180], - [1170716400000, 0.77280], - [1170802800000, 0.77290], - [1170889200000, 0.76980], - [1170975600000, 0.76850], - [1171062000000, 0.76810], - [1171148400000, 0.7690], - [1171234800000, 0.7690], - [1171321200000, 0.76980], - [1171407600000, 0.76990], - [1171494000000, 0.76510], - [1171580400000, 0.76130], - [1171666800000, 0.76160], - [1171753200000, 0.76140], - [1171839600000, 0.76140], - [1171926000000, 0.76070], - [1172012400000, 0.76020], - [1172098800000, 0.76110], - [1172185200000, 0.76220], - [1172271600000, 0.76150], - [1172358000000, 0.75980], - [1172444400000, 0.75980], - [1172530800000, 0.75920], - [1172617200000, 0.75730], - [1172703600000, 0.75660], - [1172790000000, 0.75670], - [1172876400000, 0.75910], - [1172962800000, 0.75820], - [1173049200000, 0.75850], - [1173135600000, 0.76130], - [1173222000000, 0.76310], - [1173308400000, 0.76150], - [1173394800000, 0.760], - [1173481200000, 0.76130], - [1173567600000, 0.76270], - [1173654000000, 0.76270], - [1173740400000, 0.76080], - [1173826800000, 0.75830], - [1173913200000, 0.75750], - [1173999600000, 0.75620], - [1174086000000, 0.7520], - [1174172400000, 0.75120], - [1174258800000, 0.75120], - [1174345200000, 0.75170], - [1174431600000, 0.7520], - [1174518000000, 0.75110], - [1174604400000, 0.7480], - [1174690800000, 0.75090], - [1174777200000, 0.75310], - [1174860000000, 0.75310], - [1174946400000, 0.75270], - [1175032800000, 0.74980], - [1175119200000, 0.74930], - [1175205600000, 0.75040], - [1175292000000, 0.750], - [1175378400000, 0.74910], - [1175464800000, 0.74910], - [1175551200000, 0.74850], - [1175637600000, 0.74840], - [1175724000000, 0.74920], - [1175810400000, 0.74710], - [1175896800000, 0.74590], - [1175983200000, 0.74770], - [1176069600000, 0.74770], - [1176156000000, 0.74830], - [1176242400000, 0.74580], - [1176328800000, 0.74480], - [1176415200000, 0.7430], - [1176501600000, 0.73990], - [1176588000000, 0.73950], - [1176674400000, 0.73950], - [1176760800000, 0.73780], - [1176847200000, 0.73820], - [1176933600000, 0.73620], - [1177020000000, 0.73550], - [1177106400000, 0.73480], - [1177192800000, 0.73610], - [1177279200000, 0.73610], - [1177365600000, 0.73650], - [1177452000000, 0.73620], - [1177538400000, 0.73310], - [1177624800000, 0.73390], - [1177711200000, 0.73440], - [1177797600000, 0.73270], - [1177884000000, 0.73270], - [1177970400000, 0.73360], - [1178056800000, 0.73330], - [1178143200000, 0.73590], - [1178229600000, 0.73590], - [1178316000000, 0.73720], - [1178402400000, 0.7360], - [1178488800000, 0.7360], - [1178575200000, 0.7350], - [1178661600000, 0.73650], - [1178748000000, 0.73840], - [1178834400000, 0.73950], - [1178920800000, 0.74130], - [1179007200000, 0.73970], - [1179093600000, 0.73960], - [1179180000000, 0.73850], - [1179266400000, 0.73780], - [1179352800000, 0.73660], - [1179439200000, 0.740], - [1179525600000, 0.74110], - [1179612000000, 0.74060], - [1179698400000, 0.74050], - [1179784800000, 0.74140], - [1179871200000, 0.74310], - [1179957600000, 0.74310], - [1180044000000, 0.74380], - [1180130400000, 0.74430], - [1180216800000, 0.74430], - [1180303200000, 0.74430], - [1180389600000, 0.74340], - [1180476000000, 0.74290], - [1180562400000, 0.74420], - [1180648800000, 0.7440], - [1180735200000, 0.74390], - [1180821600000, 0.74370], - [1180908000000, 0.74370], - [1180994400000, 0.74290], - [1181080800000, 0.74030], - [1181167200000, 0.73990], - [1181253600000, 0.74180], - [1181340000000, 0.74680], - [1181426400000, 0.7480], - [1181512800000, 0.7480], - [1181599200000, 0.7490], - [1181685600000, 0.74940], - [1181772000000, 0.75220], - [1181858400000, 0.75150], - [1181944800000, 0.75020], - [1182031200000, 0.74720], - [1182117600000, 0.74720], - [1182204000000, 0.74620], - [1182290400000, 0.74550], - [1182376800000, 0.74490], - [1182463200000, 0.74670], - [1182549600000, 0.74580], - [1182636000000, 0.74270], - [1182722400000, 0.74270], - [1182808800000, 0.7430], - [1182895200000, 0.74290], - [1182981600000, 0.7440], - [1183068000000, 0.7430], - [1183154400000, 0.74220], - [1183240800000, 0.73880], - [1183327200000, 0.73880], - [1183413600000, 0.73690], - [1183500000000, 0.73450], - [1183586400000, 0.73450], - [1183672800000, 0.73450], - [1183759200000, 0.73520], - [1183845600000, 0.73410], - [1183932000000, 0.73410], - [1184018400000, 0.7340], - [1184104800000, 0.73240], - [1184191200000, 0.72720], - [1184277600000, 0.72640], - [1184364000000, 0.72550], - [1184450400000, 0.72580], - [1184536800000, 0.72580], - [1184623200000, 0.72560], - [1184709600000, 0.72570], - [1184796000000, 0.72470], - [1184882400000, 0.72430], - [1184968800000, 0.72440], - [1185055200000, 0.72350], - [1185141600000, 0.72350], - [1185228000000, 0.72350], - [1185314400000, 0.72350], - [1185400800000, 0.72620], - [1185487200000, 0.72880], - [1185573600000, 0.73010], - [1185660000000, 0.73370], - [1185746400000, 0.73370], - [1185832800000, 0.73240], - [1185919200000, 0.72970], - [1186005600000, 0.73170], - [1186092000000, 0.73150], - [1186178400000, 0.72880], - [1186264800000, 0.72630], - [1186351200000, 0.72630], - [1186437600000, 0.72420], - [1186524000000, 0.72530], - [1186610400000, 0.72640], - [1186696800000, 0.7270], - [1186783200000, 0.73120], - [1186869600000, 0.73050], - [1186956000000, 0.73050], - [1187042400000, 0.73180], - [1187128800000, 0.73580], - [1187215200000, 0.74090], - [1187301600000, 0.74540], - [1187388000000, 0.74370], - [1187474400000, 0.74240], - [1187560800000, 0.74240], - [1187647200000, 0.74150], - [1187733600000, 0.74190], - [1187820000000, 0.74140], - [1187906400000, 0.73770], - [1187992800000, 0.73550], - [1188079200000, 0.73150], - [1188165600000, 0.73150], - [1188252000000, 0.7320], - [1188338400000, 0.73320], - [1188424800000, 0.73460], - [1188511200000, 0.73280], - [1188597600000, 0.73230], - [1188684000000, 0.7340], - [1188770400000, 0.7340], - [1188856800000, 0.73360], - [1188943200000, 0.73510], - [1189029600000, 0.73460], - [1189116000000, 0.73210], - [1189202400000, 0.72940], - [1189288800000, 0.72660], - [1189375200000, 0.72660], - [1189461600000, 0.72540], - [1189548000000, 0.72420], - [1189634400000, 0.72130], - [1189720800000, 0.71970], - [1189807200000, 0.72090], - [1189893600000, 0.7210], - [1189980000000, 0.7210], - [1190066400000, 0.7210], - [1190152800000, 0.72090], - [1190239200000, 0.71590], - [1190325600000, 0.71330], - [1190412000000, 0.71050], - [1190498400000, 0.70990], - [1190584800000, 0.70990], - [1190671200000, 0.70930], - [1190757600000, 0.70930], - [1190844000000, 0.70760], - [1190930400000, 0.7070], - [1191016800000, 0.70490], - [1191103200000, 0.70120], - [1191189600000, 0.70110], - [1191276000000, 0.70190], - [1191362400000, 0.70460], - [1191448800000, 0.70630], - [1191535200000, 0.70890], - [1191621600000, 0.70770], - [1191708000000, 0.70770], - [1191794400000, 0.70770], - [1191880800000, 0.70910], - [1191967200000, 0.71180], - [1192053600000, 0.70790], - [1192140000000, 0.70530], - [1192226400000, 0.7050], - [1192312800000, 0.70550], - [1192399200000, 0.70550], - [1192485600000, 0.70450], - [1192572000000, 0.70510], - [1192658400000, 0.70510], - [1192744800000, 0.70170], - [1192831200000, 0.70], - [1192917600000, 0.69950], - [1193004000000, 0.69940], - [1193090400000, 0.70140], - [1193176800000, 0.70360], - [1193263200000, 0.70210], - [1193349600000, 0.70020], - [1193436000000, 0.69670], - [1193522400000, 0.6950], - [1193612400000, 0.6950], - [1193698800000, 0.69390], - [1193785200000, 0.6940], - [1193871600000, 0.69220], - [1193958000000, 0.69190], - [1194044400000, 0.69140], - [1194130800000, 0.68940], - [1194217200000, 0.68910], - [1194303600000, 0.69040], - [1194390000000, 0.6890], - [1194476400000, 0.68340], - [1194562800000, 0.68230], - [1194649200000, 0.68070], - [1194735600000, 0.68150], - [1194822000000, 0.68150], - [1194908400000, 0.68470], - [1194994800000, 0.68590], - [1195081200000, 0.68220], - [1195167600000, 0.68270], - [1195254000000, 0.68370], - [1195340400000, 0.68230], - [1195426800000, 0.68220], - [1195513200000, 0.68220], - [1195599600000, 0.67920], - [1195686000000, 0.67460], - [1195772400000, 0.67350], - [1195858800000, 0.67310], - [1195945200000, 0.67420], - [1196031600000, 0.67440], - [1196118000000, 0.67390], - [1196204400000, 0.67310], - [1196290800000, 0.67610], - [1196377200000, 0.67610], - [1196463600000, 0.67850], - [1196550000000, 0.68180], - [1196636400000, 0.68360], - [1196722800000, 0.68230], - [1196809200000, 0.68050], - [1196895600000, 0.67930], - [1196982000000, 0.68490], - [1197068400000, 0.68330], - [1197154800000, 0.68250], - [1197241200000, 0.68250], - [1197327600000, 0.68160], - [1197414000000, 0.67990], - [1197500400000, 0.68130], - [1197586800000, 0.68090], - [1197673200000, 0.68680], - [1197759600000, 0.69330], - [1197846000000, 0.69330], - [1197932400000, 0.69450], - [1198018800000, 0.69440], - [1198105200000, 0.69460], - [1198191600000, 0.69640], - [1198278000000, 0.69650], - [1198364400000, 0.69560], - [1198450800000, 0.69560], - [1198537200000, 0.6950], - [1198623600000, 0.69480], - [1198710000000, 0.69280], - [1198796400000, 0.68870], - [1198882800000, 0.68240], - [1198969200000, 0.67940], - [1199055600000, 0.67940], - [1199142000000, 0.68030], - [1199228400000, 0.68550], - [1199314800000, 0.68240], - [1199401200000, 0.67910], - [1199487600000, 0.67830], - [1199574000000, 0.67850], - [1199660400000, 0.67850], - [1199746800000, 0.67970], - [1199833200000, 0.680], - [1199919600000, 0.68030], - [1200006000000, 0.68050], - [1200092400000, 0.6760], - [1200178800000, 0.6770], - [1200265200000, 0.6770], - [1200351600000, 0.67360], - [1200438000000, 0.67260], - [1200524400000, 0.67640], - [1200610800000, 0.68210], - [1200697200000, 0.68310], - [1200783600000, 0.68420], - [1200870000000, 0.68420], - [1200956400000, 0.68870], - [1201042800000, 0.69030], - [1201129200000, 0.68480], - [1201215600000, 0.68240], - [1201302000000, 0.67880], - [1201388400000, 0.68140], - [1201474800000, 0.68140], - [1201561200000, 0.67970], - [1201647600000, 0.67690], - [1201734000000, 0.67650], - [1201820400000, 0.67330], - [1201906800000, 0.67290], - [1201993200000, 0.67580], - [1202079600000, 0.67580], - [1202166000000, 0.6750], - [1202252400000, 0.6780], - [1202338800000, 0.68330], - [1202425200000, 0.68560], - [1202511600000, 0.69030], - [1202598000000, 0.68960], - [1202684400000, 0.68960], - [1202770800000, 0.68820], - [1202857200000, 0.68790], - [1202943600000, 0.68620], - [1203030000000, 0.68520], - [1203116400000, 0.68230], - [1203202800000, 0.68130], - [1203289200000, 0.68130], - [1203375600000, 0.68220], - [1203462000000, 0.68020], - [1203548400000, 0.68020], - [1203634800000, 0.67840], - [1203721200000, 0.67480], - [1203807600000, 0.67470], - [1203894000000, 0.67470], - [1203980400000, 0.67480], - [1204066800000, 0.67330], - [1204153200000, 0.6650], - [1204239600000, 0.66110], - [1204326000000, 0.65830], - [1204412400000, 0.6590], - [1204498800000, 0.6590], - [1204585200000, 0.65810], - [1204671600000, 0.65780], - [1204758000000, 0.65740], - [1204844400000, 0.65320], - [1204930800000, 0.65020], - [1205017200000, 0.65140], - [1205103600000, 0.65140], - [1205190000000, 0.65070], - [1205276400000, 0.6510], - [1205362800000, 0.64890], - [1205449200000, 0.64240], - [1205535600000, 0.64060], - [1205622000000, 0.63820], - [1205708400000, 0.63820], - [1205794800000, 0.63410], - [1205881200000, 0.63440], - [1205967600000, 0.63780], - [1206054000000, 0.64390], - [1206140400000, 0.64780], - [1206226800000, 0.64810], - [1206313200000, 0.64810], - [1206399600000, 0.64940], - [1206486000000, 0.64380], - [1206572400000, 0.63770], - [1206658800000, 0.63290], - [1206745200000, 0.63360], - [1206831600000, 0.63330], - [1206914400000, 0.63330], - [1207000800000, 0.6330], - [1207087200000, 0.63710], - [1207173600000, 0.64030], - [1207260000000, 0.63960], - [1207346400000, 0.63640], - [1207432800000, 0.63560], - [1207519200000, 0.63560], - [1207605600000, 0.63680], - [1207692000000, 0.63570], - [1207778400000, 0.63540], - [1207864800000, 0.6320], - [1207951200000, 0.63320], - [1208037600000, 0.63280], - [1208124000000, 0.63310], - [1208210400000, 0.63420], - [1208296800000, 0.63210], - [1208383200000, 0.63020], - [1208469600000, 0.62780], - [1208556000000, 0.63080], - [1208642400000, 0.63240], - [1208728800000, 0.63240], - [1208815200000, 0.63070], - [1208901600000, 0.62770], - [1208988000000, 0.62690], - [1209074400000, 0.63350], - [1209160800000, 0.63920], - [1209247200000, 0.640], - [1209333600000, 0.64010], - [1209420000000, 0.63960], - [1209506400000, 0.64070], - [1209592800000, 0.64230], - [1209679200000, 0.64290], - [1209765600000, 0.64720], - [1209852000000, 0.64850], - [1209938400000, 0.64860], - [1210024800000, 0.64670], - [1210111200000, 0.64440], - [1210197600000, 0.64670], - [1210284000000, 0.65090], - [1210370400000, 0.64780], - [1210456800000, 0.64610], - [1210543200000, 0.64610], - [1210629600000, 0.64680], - [1210716000000, 0.64490], - [1210802400000, 0.6470], - [1210888800000, 0.64610], - [1210975200000, 0.64520], - [1211061600000, 0.64220], - [1211148000000, 0.64220], - [1211234400000, 0.64250], - [1211320800000, 0.64140], - [1211407200000, 0.63660], - [1211493600000, 0.63460], - [1211580000000, 0.6350], - [1211666400000, 0.63460], - [1211752800000, 0.63460], - [1211839200000, 0.63430], - [1211925600000, 0.63460], - [1212012000000, 0.63790], - [1212098400000, 0.64160], - [1212184800000, 0.64420], - [1212271200000, 0.64310], - [1212357600000, 0.64310], - [1212444000000, 0.64350], - [1212530400000, 0.6440], - [1212616800000, 0.64730], - [1212703200000, 0.64690], - [1212789600000, 0.63860], - [1212876000000, 0.63560], - [1212962400000, 0.6340], - [1213048800000, 0.63460], - [1213135200000, 0.6430], - [1213221600000, 0.64520], - [1213308000000, 0.64670], - [1213394400000, 0.65060], - [1213480800000, 0.65040], - [1213567200000, 0.65030], - [1213653600000, 0.64810], - [1213740000000, 0.64510], - [1213826400000, 0.6450], - [1213912800000, 0.64410], - [1213999200000, 0.64140], - [1214085600000, 0.64090], - [1214172000000, 0.64090], - [1214258400000, 0.64280], - [1214344800000, 0.64310], - [1214431200000, 0.64180], - [1214517600000, 0.63710], - [1214604000000, 0.63490], - [1214690400000, 0.63330], - [1214776800000, 0.63340], - [1214863200000, 0.63380], - [1214949600000, 0.63420], - [1215036000000, 0.6320], - [1215122400000, 0.63180], - [1215208800000, 0.6370], - [1215295200000, 0.63680], - [1215381600000, 0.63680], - [1215468000000, 0.63830], - [1215554400000, 0.63710], - [1215640800000, 0.63710], - [1215727200000, 0.63550], - [1215813600000, 0.6320], - [1215900000000, 0.62770], - [1215986400000, 0.62760], - [1216072800000, 0.62910], - [1216159200000, 0.62740], - [1216245600000, 0.62930], - [1216332000000, 0.63110], - [1216418400000, 0.6310], - [1216504800000, 0.63120], - [1216591200000, 0.63120], - [1216677600000, 0.63040], - [1216764000000, 0.62940], - [1216850400000, 0.63480], - [1216936800000, 0.63780], - [1217023200000, 0.63680], - [1217109600000, 0.63680], - [1217196000000, 0.63680], - [1217282400000, 0.6360], - [1217368800000, 0.6370], - [1217455200000, 0.64180], - [1217541600000, 0.64110], - [1217628000000, 0.64350], - [1217714400000, 0.64270], - [1217800800000, 0.64270], - [1217887200000, 0.64190], - [1217973600000, 0.64460], - [1218060000000, 0.64680], - [1218146400000, 0.64870], - [1218232800000, 0.65940], - [1218319200000, 0.66660], - [1218405600000, 0.66660], - [1218492000000, 0.66780], - [1218578400000, 0.67120], - [1218664800000, 0.67050], - [1218751200000, 0.67180], - [1218837600000, 0.67840], - [1218924000000, 0.68110], - [1219010400000, 0.68110], - [1219096800000, 0.67940], - [1219183200000, 0.68040], - [1219269600000, 0.67810], - [1219356000000, 0.67560], - [1219442400000, 0.67350], - [1219528800000, 0.67630], - [1219615200000, 0.67620], - [1219701600000, 0.67770], - [1219788000000, 0.68150], - [1219874400000, 0.68020], - [1219960800000, 0.6780], - [1220047200000, 0.67960], - [1220133600000, 0.68170], - [1220220000000, 0.68170], - [1220306400000, 0.68320], - [1220392800000, 0.68770], - [1220479200000, 0.69120], - [1220565600000, 0.69140], - [1220652000000, 0.70090], - [1220738400000, 0.70120], - [1220824800000, 0.7010], - [1220911200000, 0.70050] - ]; - - function euroFormatter(v, axis) { - return v.toFixed(axis.tickDecimals) + "€"; - } - - function doPlot(position) { - $.plot($("#flot-multiple-axes-chart"), [{ - data: oilprices, - label: "Oil price ($)" - }, { - data: exchangerates, - label: "USD/EUR exchange rate", - yaxis: 2 - }], { - xaxes: [{ - mode: 'time' - }], - yaxes: [{ - min: 0 - }, { - // align if we are to the right - alignTicksWithAxis: position == "right" ? 1 : null, - position: position, - tickFormatter: euroFormatter - }], - legend: { - position: 'sw' - }, - grid: { - hoverable: true //IMPORTANT! this is needed for tooltip to work - }, - tooltip: true, - tooltipOpts: { - content: "%s for %x was %y", - xDateFormat: "%y-%0m-%0d", - - onHover: function(flotItem, $tooltipEl) { - // console.log(flotItem, $tooltipEl); - } - } - - }); - } - - doPlot("right"); - - $("button").click(function() { - doPlot($(this).text()); - }); -}); - -// Flot Chart Dynamic Chart - -$(function() { - - var container = $("#flot-moving-line-chart"); - - // Determine how many data points to keep based on the placeholder's initial size; - // this gives us a nice high-res plot while avoiding more than one point per pixel. - - var maximum = container.outerWidth() / 2 || 300; - - // - - var data = []; - - function getRandomData() { - - if (data.length) { - data = data.slice(1); - } - - while (data.length < maximum) { - var previous = data.length ? data[data.length - 1] : 50; - var y = previous + Math.random() * 10 - 5; - data.push(y < 0 ? 0 : y > 100 ? 100 : y); - } - - // zip the generated y values with the x values - - var res = []; - for (var i = 0; i < data.length; ++i) { - res.push([i, data[i]]) - } - - return res; - } - - // - - series = [{ - data: getRandomData(), - lines: { - fill: true - } - }]; - - // - - var plot = $.plot(container, series, { - grid: { - borderWidth: 1, - minBorderMargin: 20, - labelMargin: 10, - backgroundColor: { - colors: ["#fff", "#e4f4f4"] - }, - margin: { - top: 8, - bottom: 20, - left: 20 - }, - markings: function(axes) { - var markings = []; - var xaxis = axes.xaxis; - for (var x = Math.floor(xaxis.min); x < xaxis.max; x += xaxis.tickSize * 2) { - markings.push({ - xaxis: { - from: x, - to: x + xaxis.tickSize - }, - color: "rgba(232, 232, 255, 0.2)" - }); - } - return markings; - } - }, - xaxis: { - tickFormatter: function() { - return ""; - } - }, - yaxis: { - min: 0, - max: 110 - }, - legend: { - show: true - } - }); - - // Update the random dataset at 25FPS for a smoothly-animating chart - - setInterval(function updateRandom() { - series[0].data = getRandomData(); - plot.setData(series); - plot.draw(); - }, 40); - -}); - -// Flot Chart Bar Graph - -$(function() { - - var barOptions = { - series: { - bars: { - show: true, - barWidth: 43200000 - } - }, - xaxis: { - mode: "time", - timeformat: "%m/%d", - minTickSize: [1, "day"] - }, - grid: { - hoverable: true - }, - legend: { - show: false - }, - tooltip: true, - tooltipOpts: { - content: "x: %x, y: %y" - } - }; - var barData = { - label: "bar", - data: [ - [1354521600000, 1000], - [1355040000000, 2000], - [1355223600000, 3000], - [1355306400000, 4000], - [1355487300000, 5000], - [1355571900000, 6000] - ] - }; - $.plot($("#flot-bar-chart"), [barData], barOptions); - -}); diff --git a/static/js/plugins/flot/jquery.flot.js b/static/js/plugins/flot/jquery.flot.js deleted file mode 100755 index aabc544..0000000 --- a/static/js/plugins/flot/jquery.flot.js +++ /dev/null @@ -1,2599 +0,0 @@ -/*! Javascript plotting library for jQuery, v. 0.7. - * - * Released under the MIT license by IOLA, December 2007. - * - */ - -// first an inline dependency, jquery.colorhelpers.js, we inline it here -// for convenience - -/* Plugin for jQuery for working with colors. - * - * Version 1.1. - * - * Inspiration from jQuery color animation plugin by John Resig. - * - * Released under the MIT license by Ole Laursen, October 2009. - * - * Examples: - * - * $.color.parse("#fff").scale('rgb', 0.25).add('a', -0.5).toString() - * var c = $.color.extract($("#mydiv"), 'background-color'); - * console.log(c.r, c.g, c.b, c.a); - * $.color.make(100, 50, 25, 0.4).toString() // returns "rgba(100,50,25,0.4)" - * - * Note that .scale() and .add() return the same modified object - * instead of making a new one. - * - * V. 1.1: Fix error handling so e.g. parsing an empty string does - * produce a color rather than just crashing. - */ -(function(B){B.color={};B.color.make=function(F,E,C,D){var G={};G.r=F||0;G.g=E||0;G.b=C||0;G.a=D!=null?D:1;G.add=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]+=I}return G.normalize()};G.scale=function(J,I){for(var H=0;H<J.length;++H){G[J.charAt(H)]*=I}return G.normalize()};G.toString=function(){if(G.a>=1){return"rgb("+[G.r,G.g,G.b].join(",")+")"}else{return"rgba("+[G.r,G.g,G.b,G.a].join(",")+")"}};G.normalize=function(){function H(J,K,I){return K<J?J:(K>I?I:K)}G.r=H(0,parseInt(G.r),255);G.g=H(0,parseInt(G.g),255);G.b=H(0,parseInt(G.b),255);G.a=H(0,G.a,1);return G};G.clone=function(){return B.color.make(G.r,G.b,G.g,G.a)};return G.normalize()};B.color.extract=function(D,C){var E;do{E=D.css(C).toLowerCase();if(E!=""&&E!="transparent"){break}D=D.parent()}while(!B.nodeName(D.get(0),"body"));if(E=="rgba(0, 0, 0, 0)"){E="transparent"}return B.color.parse(E)};B.color.parse=function(F){var E,C=B.color.make;if(E=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10))}if(E=/rgba\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseInt(E[1],10),parseInt(E[2],10),parseInt(E[3],10),parseFloat(E[4]))}if(E=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55)}if(E=/rgba\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\s*\)/.exec(F)){return C(parseFloat(E[1])*2.55,parseFloat(E[2])*2.55,parseFloat(E[3])*2.55,parseFloat(E[4]))}if(E=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(F)){return C(parseInt(E[1],16),parseInt(E[2],16),parseInt(E[3],16))}if(E=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(F)){return C(parseInt(E[1]+E[1],16),parseInt(E[2]+E[2],16),parseInt(E[3]+E[3],16))}var D=B.trim(F).toLowerCase();if(D=="transparent"){return C(255,255,255,0)}else{E=A[D]||[0,0,0];return C(E[0],E[1],E[2])}};var A={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0]}})(jQuery); - -// the actual Flot code -(function($) { - function Plot(placeholder, data_, options_, plugins) { - // data is on the form: - // [ series1, series2 ... ] - // where series is either just the data as [ [x1, y1], [x2, y2], ... ] - // or { data: [ [x1, y1], [x2, y2], ... ], label: "some label", ... } - - var series = [], - options = { - // the color theme used for graphs - colors: ["#edc240", "#afd8f8", "#cb4b4b", "#4da74d", "#9440ed"], - legend: { - show: true, - noColumns: 1, // number of colums in legend table - labelFormatter: null, // fn: string -> string - labelBoxBorderColor: "#ccc", // border color for the little label boxes - container: null, // container (as jQuery object) to put legend in, null means default on top of graph - position: "ne", // position of default legend container within plot - margin: 5, // distance from grid edge to default legend container within plot - backgroundColor: null, // null means auto-detect - backgroundOpacity: 0.85 // set to 0 to avoid background - }, - xaxis: { - show: null, // null = auto-detect, true = always, false = never - position: "bottom", // or "top" - mode: null, // null or "time" - color: null, // base color, labels, ticks - tickColor: null, // possibly different color of ticks, e.g. "rgba(0,0,0,0.15)" - transform: null, // null or f: number -> number to transform axis - inverseTransform: null, // if transform is set, this should be the inverse function - min: null, // min. value to show, null means set automatically - max: null, // max. value to show, null means set automatically - autoscaleMargin: null, // margin in % to add if auto-setting min/max - ticks: null, // either [1, 3] or [[1, "a"], 3] or (fn: axis info -> ticks) or app. number of ticks for auto-ticks - tickFormatter: null, // fn: number -> string - labelWidth: null, // size of tick labels in pixels - labelHeight: null, - reserveSpace: null, // whether to reserve space even if axis isn't shown - tickLength: null, // size in pixels of ticks, or "full" for whole line - alignTicksWithAxis: null, // axis number or null for no sync - - // mode specific options - tickDecimals: null, // no. of decimals, null means auto - tickSize: null, // number or [number, "unit"] - minTickSize: null, // number or [number, "unit"] - monthNames: null, // list of names of months - timeformat: null, // format string to use - twelveHourClock: false // 12 or 24 time in time mode - }, - yaxis: { - autoscaleMargin: 0.02, - position: "left" // or "right" - }, - xaxes: [], - yaxes: [], - series: { - points: { - show: false, - radius: 3, - lineWidth: 2, // in pixels - fill: true, - fillColor: "#ffffff", - symbol: "circle" // or callback - }, - lines: { - // we don't put in show: false so we can see - // whether lines were actively disabled - lineWidth: 2, // in pixels - fill: false, - fillColor: null, - steps: false - }, - bars: { - show: false, - lineWidth: 2, // in pixels - barWidth: 1, // in units of the x axis - fill: true, - fillColor: null, - align: "left", // or "center" - horizontal: false - }, - shadowSize: 3 - }, - grid: { - show: true, - aboveData: false, - color: "#545454", // primary color used for outline and labels - backgroundColor: null, // null for transparent, else color - borderColor: null, // set if different from the grid color - tickColor: null, // color for the ticks, e.g. "rgba(0,0,0,0.15)" - labelMargin: 5, // in pixels - axisMargin: 8, // in pixels - borderWidth: 2, // in pixels - minBorderMargin: null, // in pixels, null means taken from points radius - markings: null, // array of ranges or fn: axes -> array of ranges - markingsColor: "#f4f4f4", - markingsLineWidth: 2, - // interactive stuff - clickable: false, - hoverable: false, - autoHighlight: true, // highlight in case mouse is near - mouseActiveRadius: 10 // how far the mouse can be away to activate an item - }, - hooks: {} - }, - canvas = null, // the canvas for the plot itself - overlay = null, // canvas for interactive stuff on top of plot - eventHolder = null, // jQuery object that events should be bound to - ctx = null, octx = null, - xaxes = [], yaxes = [], - plotOffset = { left: 0, right: 0, top: 0, bottom: 0}, - canvasWidth = 0, canvasHeight = 0, - plotWidth = 0, plotHeight = 0, - hooks = { - processOptions: [], - processRawData: [], - processDatapoints: [], - drawSeries: [], - draw: [], - bindEvents: [], - drawOverlay: [], - shutdown: [] - }, - plot = this; - - // public functions - plot.setData = setData; - plot.setupGrid = setupGrid; - plot.draw = draw; - plot.getPlaceholder = function() { return placeholder; }; - plot.getCanvas = function() { return canvas; }; - plot.getPlotOffset = function() { return plotOffset; }; - plot.width = function () { return plotWidth; }; - plot.height = function () { return plotHeight; }; - plot.offset = function () { - var o = eventHolder.offset(); - o.left += plotOffset.left; - o.top += plotOffset.top; - return o; - }; - plot.getData = function () { return series; }; - plot.getAxes = function () { - var res = {}, i; - $.each(xaxes.concat(yaxes), function (_, axis) { - if (axis) - res[axis.direction + (axis.n != 1 ? axis.n : "") + "axis"] = axis; - }); - return res; - }; - plot.getXAxes = function () { return xaxes; }; - plot.getYAxes = function () { return yaxes; }; - plot.c2p = canvasToAxisCoords; - plot.p2c = axisToCanvasCoords; - plot.getOptions = function () { return options; }; - plot.highlight = highlight; - plot.unhighlight = unhighlight; - plot.triggerRedrawOverlay = triggerRedrawOverlay; - plot.pointOffset = function(point) { - return { - left: parseInt(xaxes[axisNumber(point, "x") - 1].p2c(+point.x) + plotOffset.left), - top: parseInt(yaxes[axisNumber(point, "y") - 1].p2c(+point.y) + plotOffset.top) - }; - }; - plot.shutdown = shutdown; - plot.resize = function () { - getCanvasDimensions(); - resizeCanvas(canvas); - resizeCanvas(overlay); - }; - - // public attributes - plot.hooks = hooks; - - // initialize - initPlugins(plot); - parseOptions(options_); - setupCanvases(); - setData(data_); - setupGrid(); - draw(); - bindEvents(); - - - function executeHooks(hook, args) { - args = [plot].concat(args); - for (var i = 0; i < hook.length; ++i) - hook[i].apply(this, args); - } - - function initPlugins() { - for (var i = 0; i < plugins.length; ++i) { - var p = plugins[i]; - p.init(plot); - if (p.options) - $.extend(true, options, p.options); - } - } - - function parseOptions(opts) { - var i; - - $.extend(true, options, opts); - - if (options.xaxis.color == null) - options.xaxis.color = options.grid.color; - if (options.yaxis.color == null) - options.yaxis.color = options.grid.color; - - if (options.xaxis.tickColor == null) // backwards-compatibility - options.xaxis.tickColor = options.grid.tickColor; - if (options.yaxis.tickColor == null) // backwards-compatibility - options.yaxis.tickColor = options.grid.tickColor; - - if (options.grid.borderColor == null) - options.grid.borderColor = options.grid.color; - if (options.grid.tickColor == null) - options.grid.tickColor = $.color.parse(options.grid.color).scale('a', 0.22).toString(); - - // fill in defaults in axes, copy at least always the - // first as the rest of the code assumes it'll be there - for (i = 0; i < Math.max(1, options.xaxes.length); ++i) - options.xaxes[i] = $.extend(true, {}, options.xaxis, options.xaxes[i]); - for (i = 0; i < Math.max(1, options.yaxes.length); ++i) - options.yaxes[i] = $.extend(true, {}, options.yaxis, options.yaxes[i]); - - // backwards compatibility, to be removed in future - if (options.xaxis.noTicks && options.xaxis.ticks == null) - options.xaxis.ticks = options.xaxis.noTicks; - if (options.yaxis.noTicks && options.yaxis.ticks == null) - options.yaxis.ticks = options.yaxis.noTicks; - if (options.x2axis) { - options.xaxes[1] = $.extend(true, {}, options.xaxis, options.x2axis); - options.xaxes[1].position = "top"; - } - if (options.y2axis) { - options.yaxes[1] = $.extend(true, {}, options.yaxis, options.y2axis); - options.yaxes[1].position = "right"; - } - if (options.grid.coloredAreas) - options.grid.markings = options.grid.coloredAreas; - if (options.grid.coloredAreasColor) - options.grid.markingsColor = options.grid.coloredAreasColor; - if (options.lines) - $.extend(true, options.series.lines, options.lines); - if (options.points) - $.extend(true, options.series.points, options.points); - if (options.bars) - $.extend(true, options.series.bars, options.bars); - if (options.shadowSize != null) - options.series.shadowSize = options.shadowSize; - - // save options on axes for future reference - for (i = 0; i < options.xaxes.length; ++i) - getOrCreateAxis(xaxes, i + 1).options = options.xaxes[i]; - for (i = 0; i < options.yaxes.length; ++i) - getOrCreateAxis(yaxes, i + 1).options = options.yaxes[i]; - - // add hooks from options - for (var n in hooks) - if (options.hooks[n] && options.hooks[n].length) - hooks[n] = hooks[n].concat(options.hooks[n]); - - executeHooks(hooks.processOptions, [options]); - } - - function setData(d) { - series = parseData(d); - fillInSeriesOptions(); - processData(); - } - - function parseData(d) { - var res = []; - for (var i = 0; i < d.length; ++i) { - var s = $.extend(true, {}, options.series); - - if (d[i].data != null) { - s.data = d[i].data; // move the data instead of deep-copy - delete d[i].data; - - $.extend(true, s, d[i]); - - d[i].data = s.data; - } - else - s.data = d[i]; - res.push(s); - } - - return res; - } - - function axisNumber(obj, coord) { - var a = obj[coord + "axis"]; - if (typeof a == "object") // if we got a real axis, extract number - a = a.n; - if (typeof a != "number") - a = 1; // default to first axis - return a; - } - - function allAxes() { - // return flat array without annoying null entries - return $.grep(xaxes.concat(yaxes), function (a) { return a; }); - } - - function canvasToAxisCoords(pos) { - // return an object with x/y corresponding to all used axes - var res = {}, i, axis; - for (i = 0; i < xaxes.length; ++i) { - axis = xaxes[i]; - if (axis && axis.used) - res["x" + axis.n] = axis.c2p(pos.left); - } - - for (i = 0; i < yaxes.length; ++i) { - axis = yaxes[i]; - if (axis && axis.used) - res["y" + axis.n] = axis.c2p(pos.top); - } - - if (res.x1 !== undefined) - res.x = res.x1; - if (res.y1 !== undefined) - res.y = res.y1; - - return res; - } - - function axisToCanvasCoords(pos) { - // get canvas coords from the first pair of x/y found in pos - var res = {}, i, axis, key; - - for (i = 0; i < xaxes.length; ++i) { - axis = xaxes[i]; - if (axis && axis.used) { - key = "x" + axis.n; - if (pos[key] == null && axis.n == 1) - key = "x"; - - if (pos[key] != null) { - res.left = axis.p2c(pos[key]); - break; - } - } - } - - for (i = 0; i < yaxes.length; ++i) { - axis = yaxes[i]; - if (axis && axis.used) { - key = "y" + axis.n; - if (pos[key] == null && axis.n == 1) - key = "y"; - - if (pos[key] != null) { - res.top = axis.p2c(pos[key]); - break; - } - } - } - - return res; - } - - function getOrCreateAxis(axes, number) { - if (!axes[number - 1]) - axes[number - 1] = { - n: number, // save the number for future reference - direction: axes == xaxes ? "x" : "y", - options: $.extend(true, {}, axes == xaxes ? options.xaxis : options.yaxis) - }; - - return axes[number - 1]; - } - - function fillInSeriesOptions() { - var i; - - // collect what we already got of colors - var neededColors = series.length, - usedColors = [], - assignedColors = []; - for (i = 0; i < series.length; ++i) { - var sc = series[i].color; - if (sc != null) { - --neededColors; - if (typeof sc == "number") - assignedColors.push(sc); - else - usedColors.push($.color.parse(series[i].color)); - } - } - - // we might need to generate more colors if higher indices - // are assigned - for (i = 0; i < assignedColors.length; ++i) { - neededColors = Math.max(neededColors, assignedColors[i] + 1); - } - - // produce colors as needed - var colors = [], variation = 0; - i = 0; - while (colors.length < neededColors) { - var c; - if (options.colors.length == i) // check degenerate case - c = $.color.make(100, 100, 100); - else - c = $.color.parse(options.colors[i]); - - // vary color if needed - var sign = variation % 2 == 1 ? -1 : 1; - c.scale('rgb', 1 + sign * Math.ceil(variation / 2) * 0.2) - - // FIXME: if we're getting to close to something else, - // we should probably skip this one - colors.push(c); - - ++i; - if (i >= options.colors.length) { - i = 0; - ++variation; - } - } - - // fill in the options - var colori = 0, s; - for (i = 0; i < series.length; ++i) { - s = series[i]; - - // assign colors - if (s.color == null) { - s.color = colors[colori].toString(); - ++colori; - } - else if (typeof s.color == "number") - s.color = colors[s.color].toString(); - - // turn on lines automatically in case nothing is set - if (s.lines.show == null) { - var v, show = true; - for (v in s) - if (s[v] && s[v].show) { - show = false; - break; - } - if (show) - s.lines.show = true; - } - - // setup axes - s.xaxis = getOrCreateAxis(xaxes, axisNumber(s, "x")); - s.yaxis = getOrCreateAxis(yaxes, axisNumber(s, "y")); - } - } - - function processData() { - var topSentry = Number.POSITIVE_INFINITY, - bottomSentry = Number.NEGATIVE_INFINITY, - fakeInfinity = Number.MAX_VALUE, - i, j, k, m, length, - s, points, ps, x, y, axis, val, f, p; - - function updateAxis(axis, min, max) { - if (min < axis.datamin && min != -fakeInfinity) - axis.datamin = min; - if (max > axis.datamax && max != fakeInfinity) - axis.datamax = max; - } - - $.each(allAxes(), function (_, axis) { - // init axis - axis.datamin = topSentry; - axis.datamax = bottomSentry; - axis.used = false; - }); - - for (i = 0; i < series.length; ++i) { - s = series[i]; - s.datapoints = { points: [] }; - - executeHooks(hooks.processRawData, [ s, s.data, s.datapoints ]); - } - - // first pass: clean and copy data - for (i = 0; i < series.length; ++i) { - s = series[i]; - - var data = s.data, format = s.datapoints.format; - - if (!format) { - format = []; - // find out how to copy - format.push({ x: true, number: true, required: true }); - format.push({ y: true, number: true, required: true }); - - if (s.bars.show || (s.lines.show && s.lines.fill)) { - format.push({ y: true, number: true, required: false, defaultValue: 0 }); - if (s.bars.horizontal) { - delete format[format.length - 1].y; - format[format.length - 1].x = true; - } - } - - s.datapoints.format = format; - } - - if (s.datapoints.pointsize != null) - continue; // already filled in - - s.datapoints.pointsize = format.length; - - ps = s.datapoints.pointsize; - points = s.datapoints.points; - - insertSteps = s.lines.show && s.lines.steps; - s.xaxis.used = s.yaxis.used = true; - - for (j = k = 0; j < data.length; ++j, k += ps) { - p = data[j]; - - var nullify = p == null; - if (!nullify) { - for (m = 0; m < ps; ++m) { - val = p[m]; - f = format[m]; - - if (f) { - if (f.number && val != null) { - val = +val; // convert to number - if (isNaN(val)) - val = null; - else if (val == Infinity) - val = fakeInfinity; - else if (val == -Infinity) - val = -fakeInfinity; - } - - if (val == null) { - if (f.required) - nullify = true; - - if (f.defaultValue != null) - val = f.defaultValue; - } - } - - points[k + m] = val; - } - } - - if (nullify) { - for (m = 0; m < ps; ++m) { - val = points[k + m]; - if (val != null) { - f = format[m]; - // extract min/max info - if (f.x) - updateAxis(s.xaxis, val, val); - if (f.y) - updateAxis(s.yaxis, val, val); - } - points[k + m] = null; - } - } - else { - // a little bit of line specific stuff that - // perhaps shouldn't be here, but lacking - // better means... - if (insertSteps && k > 0 - && points[k - ps] != null - && points[k - ps] != points[k] - && points[k - ps + 1] != points[k + 1]) { - // copy the point to make room for a middle point - for (m = 0; m < ps; ++m) - points[k + ps + m] = points[k + m]; - - // middle point has same y - points[k + 1] = points[k - ps + 1]; - - // we've added a point, better reflect that - k += ps; - } - } - } - } - - // give the hooks a chance to run - for (i = 0; i < series.length; ++i) { - s = series[i]; - - executeHooks(hooks.processDatapoints, [ s, s.datapoints]); - } - - // second pass: find datamax/datamin for auto-scaling - for (i = 0; i < series.length; ++i) { - s = series[i]; - points = s.datapoints.points, - ps = s.datapoints.pointsize; - - var xmin = topSentry, ymin = topSentry, - xmax = bottomSentry, ymax = bottomSentry; - - for (j = 0; j < points.length; j += ps) { - if (points[j] == null) - continue; - - for (m = 0; m < ps; ++m) { - val = points[j + m]; - f = format[m]; - if (!f || val == fakeInfinity || val == -fakeInfinity) - continue; - - if (f.x) { - if (val < xmin) - xmin = val; - if (val > xmax) - xmax = val; - } - if (f.y) { - if (val < ymin) - ymin = val; - if (val > ymax) - ymax = val; - } - } - } - - if (s.bars.show) { - // make sure we got room for the bar on the dancing floor - var delta = s.bars.align == "left" ? 0 : -s.bars.barWidth/2; - if (s.bars.horizontal) { - ymin += delta; - ymax += delta + s.bars.barWidth; - } - else { - xmin += delta; - xmax += delta + s.bars.barWidth; - } - } - - updateAxis(s.xaxis, xmin, xmax); - updateAxis(s.yaxis, ymin, ymax); - } - - $.each(allAxes(), function (_, axis) { - if (axis.datamin == topSentry) - axis.datamin = null; - if (axis.datamax == bottomSentry) - axis.datamax = null; - }); - } - - function makeCanvas(skipPositioning, cls) { - var c = document.createElement('canvas'); - c.className = cls; - c.width = canvasWidth; - c.height = canvasHeight; - - if (!skipPositioning) - $(c).css({ position: 'absolute', left: 0, top: 0 }); - - $(c).appendTo(placeholder); - - if (!c.getContext) // excanvas hack - c = window.G_vmlCanvasManager.initElement(c); - - // used for resetting in case we get replotted - c.getContext("2d").save(); - - return c; - } - - function getCanvasDimensions() { - canvasWidth = placeholder.width(); - canvasHeight = placeholder.height(); - - if (canvasWidth <= 0 || canvasHeight <= 0) - throw "Invalid dimensions for plot, width = " + canvasWidth + ", height = " + canvasHeight; - } - - function resizeCanvas(c) { - // resizing should reset the state (excanvas seems to be - // buggy though) - if (c.width != canvasWidth) - c.width = canvasWidth; - - if (c.height != canvasHeight) - c.height = canvasHeight; - - // so try to get back to the initial state (even if it's - // gone now, this should be safe according to the spec) - var cctx = c.getContext("2d"); - cctx.restore(); - - // and save again - cctx.save(); - } - - function setupCanvases() { - var reused, - existingCanvas = placeholder.children("canvas.base"), - existingOverlay = placeholder.children("canvas.overlay"); - - if (existingCanvas.length == 0 || existingOverlay == 0) { - // init everything - - placeholder.html(""); // make sure placeholder is clear - - placeholder.css({ padding: 0 }); // padding messes up the positioning - - if (placeholder.css("position") == 'static') - placeholder.css("position", "relative"); // for positioning labels and overlay - - getCanvasDimensions(); - - canvas = makeCanvas(true, "base"); - overlay = makeCanvas(false, "overlay"); // overlay canvas for interactive features - - reused = false; - } - else { - // reuse existing elements - - canvas = existingCanvas.get(0); - overlay = existingOverlay.get(0); - - reused = true; - } - - ctx = canvas.getContext("2d"); - octx = overlay.getContext("2d"); - - // we include the canvas in the event holder too, because IE 7 - // sometimes has trouble with the stacking order - eventHolder = $([overlay, canvas]); - - if (reused) { - // run shutdown in the old plot object - placeholder.data("plot").shutdown(); - - // reset reused canvases - plot.resize(); - - // make sure overlay pixels are cleared (canvas is cleared when we redraw) - octx.clearRect(0, 0, canvasWidth, canvasHeight); - - // then whack any remaining obvious garbage left - eventHolder.unbind(); - placeholder.children().not([canvas, overlay]).remove(); - } - - // save in case we get replotted - placeholder.data("plot", plot); - } - - function bindEvents() { - // bind events - if (options.grid.hoverable) { - eventHolder.mousemove(onMouseMove); - eventHolder.mouseleave(onMouseLeave); - } - - if (options.grid.clickable) - eventHolder.click(onClick); - - executeHooks(hooks.bindEvents, [eventHolder]); - } - - function shutdown() { - if (redrawTimeout) - clearTimeout(redrawTimeout); - - eventHolder.unbind("mousemove", onMouseMove); - eventHolder.unbind("mouseleave", onMouseLeave); - eventHolder.unbind("click", onClick); - - executeHooks(hooks.shutdown, [eventHolder]); - } - - function setTransformationHelpers(axis) { - // set helper functions on the axis, assumes plot area - // has been computed already - - function identity(x) { return x; } - - var s, m, t = axis.options.transform || identity, - it = axis.options.inverseTransform; - - // precompute how much the axis is scaling a point - // in canvas space - if (axis.direction == "x") { - s = axis.scale = plotWidth / Math.abs(t(axis.max) - t(axis.min)); - m = Math.min(t(axis.max), t(axis.min)); - } - else { - s = axis.scale = plotHeight / Math.abs(t(axis.max) - t(axis.min)); - s = -s; - m = Math.max(t(axis.max), t(axis.min)); - } - - // data point to canvas coordinate - if (t == identity) // slight optimization - axis.p2c = function (p) { return (p - m) * s; }; - else - axis.p2c = function (p) { return (t(p) - m) * s; }; - // canvas coordinate to data point - if (!it) - axis.c2p = function (c) { return m + c / s; }; - else - axis.c2p = function (c) { return it(m + c / s); }; - } - - function measureTickLabels(axis) { - var opts = axis.options, i, ticks = axis.ticks || [], labels = [], - l, w = opts.labelWidth, h = opts.labelHeight, dummyDiv; - - function makeDummyDiv(labels, width) { - return $('<div style="position:absolute;top:-10000px;' + width + 'font-size:smaller">' + - '<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis">' - + labels.join("") + '</div></div>') - .appendTo(placeholder); - } - - if (axis.direction == "x") { - // to avoid measuring the widths of the labels (it's slow), we - // construct fixed-size boxes and put the labels inside - // them, we don't need the exact figures and the - // fixed-size box content is easy to center - if (w == null) - w = Math.floor(canvasWidth / (ticks.length > 0 ? ticks.length : 1)); - - // measure x label heights - if (h == null) { - labels = []; - for (i = 0; i < ticks.length; ++i) { - l = ticks[i].label; - if (l) - labels.push('<div class="tickLabel" style="float:left;width:' + w + 'px">' + l + '</div>'); - } - - if (labels.length > 0) { - // stick them all in the same div and measure - // collective height - labels.push('<div style="clear:left"></div>'); - dummyDiv = makeDummyDiv(labels, "width:10000px;"); - h = dummyDiv.height(); - dummyDiv.remove(); - } - } - } - else if (w == null || h == null) { - // calculate y label dimensions - for (i = 0; i < ticks.length; ++i) { - l = ticks[i].label; - if (l) - labels.push('<div class="tickLabel">' + l + '</div>'); - } - - if (labels.length > 0) { - dummyDiv = makeDummyDiv(labels, ""); - if (w == null) - w = dummyDiv.children().width(); - if (h == null) - h = dummyDiv.find("div.tickLabel").height(); - dummyDiv.remove(); - } - } - - if (w == null) - w = 0; - if (h == null) - h = 0; - - axis.labelWidth = w; - axis.labelHeight = h; - } - - function allocateAxisBoxFirstPhase(axis) { - // find the bounding box of the axis by looking at label - // widths/heights and ticks, make room by diminishing the - // plotOffset - - var lw = axis.labelWidth, - lh = axis.labelHeight, - pos = axis.options.position, - tickLength = axis.options.tickLength, - axismargin = options.grid.axisMargin, - padding = options.grid.labelMargin, - all = axis.direction == "x" ? xaxes : yaxes, - index; - - // determine axis margin - var samePosition = $.grep(all, function (a) { - return a && a.options.position == pos && a.reserveSpace; - }); - if ($.inArray(axis, samePosition) == samePosition.length - 1) - axismargin = 0; // outermost - - // determine tick length - if we're innermost, we can use "full" - if (tickLength == null) - tickLength = "full"; - - var sameDirection = $.grep(all, function (a) { - return a && a.reserveSpace; - }); - - var innermost = $.inArray(axis, sameDirection) == 0; - if (!innermost && tickLength == "full") - tickLength = 5; - - if (!isNaN(+tickLength)) - padding += +tickLength; - - // compute box - if (axis.direction == "x") { - lh += padding; - - if (pos == "bottom") { - plotOffset.bottom += lh + axismargin; - axis.box = { top: canvasHeight - plotOffset.bottom, height: lh }; - } - else { - axis.box = { top: plotOffset.top + axismargin, height: lh }; - plotOffset.top += lh + axismargin; - } - } - else { - lw += padding; - - if (pos == "left") { - axis.box = { left: plotOffset.left + axismargin, width: lw }; - plotOffset.left += lw + axismargin; - } - else { - plotOffset.right += lw + axismargin; - axis.box = { left: canvasWidth - plotOffset.right, width: lw }; - } - } - - // save for future reference - axis.position = pos; - axis.tickLength = tickLength; - axis.box.padding = padding; - axis.innermost = innermost; - } - - function allocateAxisBoxSecondPhase(axis) { - // set remaining bounding box coordinates - if (axis.direction == "x") { - axis.box.left = plotOffset.left; - axis.box.width = plotWidth; - } - else { - axis.box.top = plotOffset.top; - axis.box.height = plotHeight; - } - } - - function setupGrid() { - var i, axes = allAxes(); - - // first calculate the plot and axis box dimensions - - $.each(axes, function (_, axis) { - axis.show = axis.options.show; - if (axis.show == null) - axis.show = axis.used; // by default an axis is visible if it's got data - - axis.reserveSpace = axis.show || axis.options.reserveSpace; - - setRange(axis); - }); - - allocatedAxes = $.grep(axes, function (axis) { return axis.reserveSpace; }); - - plotOffset.left = plotOffset.right = plotOffset.top = plotOffset.bottom = 0; - if (options.grid.show) { - $.each(allocatedAxes, function (_, axis) { - // make the ticks - setupTickGeneration(axis); - setTicks(axis); - snapRangeToTicks(axis, axis.ticks); - - // find labelWidth/Height for axis - measureTickLabels(axis); - }); - - // with all dimensions in house, we can compute the - // axis boxes, start from the outside (reverse order) - for (i = allocatedAxes.length - 1; i >= 0; --i) - allocateAxisBoxFirstPhase(allocatedAxes[i]); - - // make sure we've got enough space for things that - // might stick out - var minMargin = options.grid.minBorderMargin; - if (minMargin == null) { - minMargin = 0; - for (i = 0; i < series.length; ++i) - minMargin = Math.max(minMargin, series[i].points.radius + series[i].points.lineWidth/2); - } - - for (var a in plotOffset) { - plotOffset[a] += options.grid.borderWidth; - plotOffset[a] = Math.max(minMargin, plotOffset[a]); - } - } - - plotWidth = canvasWidth - plotOffset.left - plotOffset.right; - plotHeight = canvasHeight - plotOffset.bottom - plotOffset.top; - - // now we got the proper plotWidth/Height, we can compute the scaling - $.each(axes, function (_, axis) { - setTransformationHelpers(axis); - }); - - if (options.grid.show) { - $.each(allocatedAxes, function (_, axis) { - allocateAxisBoxSecondPhase(axis); - }); - - insertAxisLabels(); - } - - insertLegend(); - } - - function setRange(axis) { - var opts = axis.options, - min = +(opts.min != null ? opts.min : axis.datamin), - max = +(opts.max != null ? opts.max : axis.datamax), - delta = max - min; - - if (delta == 0.0) { - // degenerate case - var widen = max == 0 ? 1 : 0.01; - - if (opts.min == null) - min -= widen; - // always widen max if we couldn't widen min to ensure we - // don't fall into min == max which doesn't work - if (opts.max == null || opts.min != null) - max += widen; - } - else { - // consider autoscaling - var margin = opts.autoscaleMargin; - if (margin != null) { - if (opts.min == null) { - min -= delta * margin; - // make sure we don't go below zero if all values - // are positive - if (min < 0 && axis.datamin != null && axis.datamin >= 0) - min = 0; - } - if (opts.max == null) { - max += delta * margin; - if (max > 0 && axis.datamax != null && axis.datamax <= 0) - max = 0; - } - } - } - axis.min = min; - axis.max = max; - } - - function setupTickGeneration(axis) { - var opts = axis.options; - - // estimate number of ticks - var noTicks; - if (typeof opts.ticks == "number" && opts.ticks > 0) - noTicks = opts.ticks; - else - // heuristic based on the model a*sqrt(x) fitted to - // some data points that seemed reasonable - noTicks = 0.3 * Math.sqrt(axis.direction == "x" ? canvasWidth : canvasHeight); - - var delta = (axis.max - axis.min) / noTicks, - size, generator, unit, formatter, i, magn, norm; - - if (opts.mode == "time") { - // pretty handling of time - - // map of app. size of time units in milliseconds - var timeUnitSize = { - "second": 1000, - "minute": 60 * 1000, - "hour": 60 * 60 * 1000, - "day": 24 * 60 * 60 * 1000, - "month": 30 * 24 * 60 * 60 * 1000, - "year": 365.2425 * 24 * 60 * 60 * 1000 - }; - - - // the allowed tick sizes, after 1 year we use - // an integer algorithm - var spec = [ - [1, "second"], [2, "second"], [5, "second"], [10, "second"], - [30, "second"], - [1, "minute"], [2, "minute"], [5, "minute"], [10, "minute"], - [30, "minute"], - [1, "hour"], [2, "hour"], [4, "hour"], - [8, "hour"], [12, "hour"], - [1, "day"], [2, "day"], [3, "day"], - [0.25, "month"], [0.5, "month"], [1, "month"], - [2, "month"], [3, "month"], [6, "month"], - [1, "year"] - ]; - - var minSize = 0; - if (opts.minTickSize != null) { - if (typeof opts.tickSize == "number") - minSize = opts.tickSize; - else - minSize = opts.minTickSize[0] * timeUnitSize[opts.minTickSize[1]]; - } - - for (var i = 0; i < spec.length - 1; ++i) - if (delta < (spec[i][0] * timeUnitSize[spec[i][1]] - + spec[i + 1][0] * timeUnitSize[spec[i + 1][1]]) / 2 - && spec[i][0] * timeUnitSize[spec[i][1]] >= minSize) - break; - size = spec[i][0]; - unit = spec[i][1]; - - // special-case the possibility of several years - if (unit == "year") { - magn = Math.pow(10, Math.floor(Math.log(delta / timeUnitSize.year) / Math.LN10)); - norm = (delta / timeUnitSize.year) / magn; - if (norm < 1.5) - size = 1; - else if (norm < 3) - size = 2; - else if (norm < 7.5) - size = 5; - else - size = 10; - - size *= magn; - } - - axis.tickSize = opts.tickSize || [size, unit]; - - generator = function(axis) { - var ticks = [], - tickSize = axis.tickSize[0], unit = axis.tickSize[1], - d = new Date(axis.min); - - var step = tickSize * timeUnitSize[unit]; - - if (unit == "second") - d.setUTCSeconds(floorInBase(d.getUTCSeconds(), tickSize)); - if (unit == "minute") - d.setUTCMinutes(floorInBase(d.getUTCMinutes(), tickSize)); - if (unit == "hour") - d.setUTCHours(floorInBase(d.getUTCHours(), tickSize)); - if (unit == "month") - d.setUTCMonth(floorInBase(d.getUTCMonth(), tickSize)); - if (unit == "year") - d.setUTCFullYear(floorInBase(d.getUTCFullYear(), tickSize)); - - // reset smaller components - d.setUTCMilliseconds(0); - if (step >= timeUnitSize.minute) - d.setUTCSeconds(0); - if (step >= timeUnitSize.hour) - d.setUTCMinutes(0); - if (step >= timeUnitSize.day) - d.setUTCHours(0); - if (step >= timeUnitSize.day * 4) - d.setUTCDate(1); - if (step >= timeUnitSize.year) - d.setUTCMonth(0); - - - var carry = 0, v = Number.NaN, prev; - do { - prev = v; - v = d.getTime(); - ticks.push(v); - if (unit == "month") { - if (tickSize < 1) { - // a bit complicated - we'll divide the month - // up but we need to take care of fractions - // so we don't end up in the middle of a day - d.setUTCDate(1); - var start = d.getTime(); - d.setUTCMonth(d.getUTCMonth() + 1); - var end = d.getTime(); - d.setTime(v + carry * timeUnitSize.hour + (end - start) * tickSize); - carry = d.getUTCHours(); - d.setUTCHours(0); - } - else - d.setUTCMonth(d.getUTCMonth() + tickSize); - } - else if (unit == "year") { - d.setUTCFullYear(d.getUTCFullYear() + tickSize); - } - else - d.setTime(v + step); - } while (v < axis.max && v != prev); - - return ticks; - }; - - formatter = function (v, axis) { - var d = new Date(v); - - // first check global format - if (opts.timeformat != null) - return $.plot.formatDate(d, opts.timeformat, opts.monthNames); - - var t = axis.tickSize[0] * timeUnitSize[axis.tickSize[1]]; - var span = axis.max - axis.min; - var suffix = (opts.twelveHourClock) ? " %p" : ""; - - if (t < timeUnitSize.minute) - fmt = "%h:%M:%S" + suffix; - else if (t < timeUnitSize.day) { - if (span < 2 * timeUnitSize.day) - fmt = "%h:%M" + suffix; - else - fmt = "%b %d %h:%M" + suffix; - } - else if (t < timeUnitSize.month) - fmt = "%b %d"; - else if (t < timeUnitSize.year) { - if (span < timeUnitSize.year) - fmt = "%b"; - else - fmt = "%b %y"; - } - else - fmt = "%y"; - - return $.plot.formatDate(d, fmt, opts.monthNames); - }; - } - else { - // pretty rounding of base-10 numbers - var maxDec = opts.tickDecimals; - var dec = -Math.floor(Math.log(delta) / Math.LN10); - if (maxDec != null && dec > maxDec) - dec = maxDec; - - magn = Math.pow(10, -dec); - norm = delta / magn; // norm is between 1.0 and 10.0 - - if (norm < 1.5) - size = 1; - else if (norm < 3) { - size = 2; - // special case for 2.5, requires an extra decimal - if (norm > 2.25 && (maxDec == null || dec + 1 <= maxDec)) { - size = 2.5; - ++dec; - } - } - else if (norm < 7.5) - size = 5; - else - size = 10; - - size *= magn; - - if (opts.minTickSize != null && size < opts.minTickSize) - size = opts.minTickSize; - - axis.tickDecimals = Math.max(0, maxDec != null ? maxDec : dec); - axis.tickSize = opts.tickSize || size; - - generator = function (axis) { - var ticks = []; - - // spew out all possible ticks - var start = floorInBase(axis.min, axis.tickSize), - i = 0, v = Number.NaN, prev; - do { - prev = v; - v = start + i * axis.tickSize; - ticks.push(v); - ++i; - } while (v < axis.max && v != prev); - return ticks; - }; - - formatter = function (v, axis) { - return v.toFixed(axis.tickDecimals); - }; - } - - if (opts.alignTicksWithAxis != null) { - var otherAxis = (axis.direction == "x" ? xaxes : yaxes)[opts.alignTicksWithAxis - 1]; - if (otherAxis && otherAxis.used && otherAxis != axis) { - // consider snapping min/max to outermost nice ticks - var niceTicks = generator(axis); - if (niceTicks.length > 0) { - if (opts.min == null) - axis.min = Math.min(axis.min, niceTicks[0]); - if (opts.max == null && niceTicks.length > 1) - axis.max = Math.max(axis.max, niceTicks[niceTicks.length - 1]); - } - - generator = function (axis) { - // copy ticks, scaled to this axis - var ticks = [], v, i; - for (i = 0; i < otherAxis.ticks.length; ++i) { - v = (otherAxis.ticks[i].v - otherAxis.min) / (otherAxis.max - otherAxis.min); - v = axis.min + v * (axis.max - axis.min); - ticks.push(v); - } - return ticks; - }; - - // we might need an extra decimal since forced - // ticks don't necessarily fit naturally - if (axis.mode != "time" && opts.tickDecimals == null) { - var extraDec = Math.max(0, -Math.floor(Math.log(delta) / Math.LN10) + 1), - ts = generator(axis); - - // only proceed if the tick interval rounded - // with an extra decimal doesn't give us a - // zero at end - if (!(ts.length > 1 && /\..*0$/.test((ts[1] - ts[0]).toFixed(extraDec)))) - axis.tickDecimals = extraDec; - } - } - } - - axis.tickGenerator = generator; - if ($.isFunction(opts.tickFormatter)) - axis.tickFormatter = function (v, axis) { return "" + opts.tickFormatter(v, axis); }; - else - axis.tickFormatter = formatter; - } - - function setTicks(axis) { - var oticks = axis.options.ticks, ticks = []; - if (oticks == null || (typeof oticks == "number" && oticks > 0)) - ticks = axis.tickGenerator(axis); - else if (oticks) { - if ($.isFunction(oticks)) - // generate the ticks - ticks = oticks({ min: axis.min, max: axis.max }); - else - ticks = oticks; - } - - // clean up/labelify the supplied ticks, copy them over - var i, v; - axis.ticks = []; - for (i = 0; i < ticks.length; ++i) { - var label = null; - var t = ticks[i]; - if (typeof t == "object") { - v = +t[0]; - if (t.length > 1) - label = t[1]; - } - else - v = +t; - if (label == null) - label = axis.tickFormatter(v, axis); - if (!isNaN(v)) - axis.ticks.push({ v: v, label: label }); - } - } - - function snapRangeToTicks(axis, ticks) { - if (axis.options.autoscaleMargin && ticks.length > 0) { - // snap to ticks - if (axis.options.min == null) - axis.min = Math.min(axis.min, ticks[0].v); - if (axis.options.max == null && ticks.length > 1) - axis.max = Math.max(axis.max, ticks[ticks.length - 1].v); - } - } - - function draw() { - ctx.clearRect(0, 0, canvasWidth, canvasHeight); - - var grid = options.grid; - - // draw background, if any - if (grid.show && grid.backgroundColor) - drawBackground(); - - if (grid.show && !grid.aboveData) - drawGrid(); - - for (var i = 0; i < series.length; ++i) { - executeHooks(hooks.drawSeries, [ctx, series[i]]); - drawSeries(series[i]); - } - - executeHooks(hooks.draw, [ctx]); - - if (grid.show && grid.aboveData) - drawGrid(); - } - - function extractRange(ranges, coord) { - var axis, from, to, key, axes = allAxes(); - - for (i = 0; i < axes.length; ++i) { - axis = axes[i]; - if (axis.direction == coord) { - key = coord + axis.n + "axis"; - if (!ranges[key] && axis.n == 1) - key = coord + "axis"; // support x1axis as xaxis - if (ranges[key]) { - from = ranges[key].from; - to = ranges[key].to; - break; - } - } - } - - // backwards-compat stuff - to be removed in future - if (!ranges[key]) { - axis = coord == "x" ? xaxes[0] : yaxes[0]; - from = ranges[coord + "1"]; - to = ranges[coord + "2"]; - } - - // auto-reverse as an added bonus - if (from != null && to != null && from > to) { - var tmp = from; - from = to; - to = tmp; - } - - return { from: from, to: to, axis: axis }; - } - - function drawBackground() { - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - ctx.fillStyle = getColorOrGradient(options.grid.backgroundColor, plotHeight, 0, "rgba(255, 255, 255, 0)"); - ctx.fillRect(0, 0, plotWidth, plotHeight); - ctx.restore(); - } - - function drawGrid() { - var i; - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - // draw markings - var markings = options.grid.markings; - if (markings) { - if ($.isFunction(markings)) { - var axes = plot.getAxes(); - // xmin etc. is backwards compatibility, to be - // removed in the future - axes.xmin = axes.xaxis.min; - axes.xmax = axes.xaxis.max; - axes.ymin = axes.yaxis.min; - axes.ymax = axes.yaxis.max; - - markings = markings(axes); - } - - for (i = 0; i < markings.length; ++i) { - var m = markings[i], - xrange = extractRange(m, "x"), - yrange = extractRange(m, "y"); - - // fill in missing - if (xrange.from == null) - xrange.from = xrange.axis.min; - if (xrange.to == null) - xrange.to = xrange.axis.max; - if (yrange.from == null) - yrange.from = yrange.axis.min; - if (yrange.to == null) - yrange.to = yrange.axis.max; - - // clip - if (xrange.to < xrange.axis.min || xrange.from > xrange.axis.max || - yrange.to < yrange.axis.min || yrange.from > yrange.axis.max) - continue; - - xrange.from = Math.max(xrange.from, xrange.axis.min); - xrange.to = Math.min(xrange.to, xrange.axis.max); - yrange.from = Math.max(yrange.from, yrange.axis.min); - yrange.to = Math.min(yrange.to, yrange.axis.max); - - if (xrange.from == xrange.to && yrange.from == yrange.to) - continue; - - // then draw - xrange.from = xrange.axis.p2c(xrange.from); - xrange.to = xrange.axis.p2c(xrange.to); - yrange.from = yrange.axis.p2c(yrange.from); - yrange.to = yrange.axis.p2c(yrange.to); - - if (xrange.from == xrange.to || yrange.from == yrange.to) { - // draw line - ctx.beginPath(); - ctx.strokeStyle = m.color || options.grid.markingsColor; - ctx.lineWidth = m.lineWidth || options.grid.markingsLineWidth; - ctx.moveTo(xrange.from, yrange.from); - ctx.lineTo(xrange.to, yrange.to); - ctx.stroke(); - } - else { - // fill area - ctx.fillStyle = m.color || options.grid.markingsColor; - ctx.fillRect(xrange.from, yrange.to, - xrange.to - xrange.from, - yrange.from - yrange.to); - } - } - } - - // draw the ticks - var axes = allAxes(), bw = options.grid.borderWidth; - - for (var j = 0; j < axes.length; ++j) { - var axis = axes[j], box = axis.box, - t = axis.tickLength, x, y, xoff, yoff; - if (!axis.show || axis.ticks.length == 0) - continue - - ctx.strokeStyle = axis.options.tickColor || $.color.parse(axis.options.color).scale('a', 0.22).toString(); - ctx.lineWidth = 1; - - // find the edges - if (axis.direction == "x") { - x = 0; - if (t == "full") - y = (axis.position == "top" ? 0 : plotHeight); - else - y = box.top - plotOffset.top + (axis.position == "top" ? box.height : 0); - } - else { - y = 0; - if (t == "full") - x = (axis.position == "left" ? 0 : plotWidth); - else - x = box.left - plotOffset.left + (axis.position == "left" ? box.width : 0); - } - - // draw tick bar - if (!axis.innermost) { - ctx.beginPath(); - xoff = yoff = 0; - if (axis.direction == "x") - xoff = plotWidth; - else - yoff = plotHeight; - - if (ctx.lineWidth == 1) { - x = Math.floor(x) + 0.5; - y = Math.floor(y) + 0.5; - } - - ctx.moveTo(x, y); - ctx.lineTo(x + xoff, y + yoff); - ctx.stroke(); - } - - // draw ticks - ctx.beginPath(); - for (i = 0; i < axis.ticks.length; ++i) { - var v = axis.ticks[i].v; - - xoff = yoff = 0; - - if (v < axis.min || v > axis.max - // skip those lying on the axes if we got a border - || (t == "full" && bw > 0 - && (v == axis.min || v == axis.max))) - continue; - - if (axis.direction == "x") { - x = axis.p2c(v); - yoff = t == "full" ? -plotHeight : t; - - if (axis.position == "top") - yoff = -yoff; - } - else { - y = axis.p2c(v); - xoff = t == "full" ? -plotWidth : t; - - if (axis.position == "left") - xoff = -xoff; - } - - if (ctx.lineWidth == 1) { - if (axis.direction == "x") - x = Math.floor(x) + 0.5; - else - y = Math.floor(y) + 0.5; - } - - ctx.moveTo(x, y); - ctx.lineTo(x + xoff, y + yoff); - } - - ctx.stroke(); - } - - - // draw border - if (bw) { - ctx.lineWidth = bw; - ctx.strokeStyle = options.grid.borderColor; - ctx.strokeRect(-bw/2, -bw/2, plotWidth + bw, plotHeight + bw); - } - - ctx.restore(); - } - - function insertAxisLabels() { - placeholder.find(".tickLabels").remove(); - - var html = ['<div class="tickLabels" style="font-size:smaller">']; - - var axes = allAxes(); - for (var j = 0; j < axes.length; ++j) { - var axis = axes[j], box = axis.box; - if (!axis.show) - continue; - //debug: html.push('<div style="position:absolute;opacity:0.10;background-color:red;left:' + box.left + 'px;top:' + box.top + 'px;width:' + box.width + 'px;height:' + box.height + 'px"></div>') - html.push('<div class="' + axis.direction + 'Axis ' + axis.direction + axis.n + 'Axis" style="color:' + axis.options.color + '">'); - for (var i = 0; i < axis.ticks.length; ++i) { - var tick = axis.ticks[i]; - if (!tick.label || tick.v < axis.min || tick.v > axis.max) - continue; - - var pos = {}, align; - - if (axis.direction == "x") { - align = "center"; - pos.left = Math.round(plotOffset.left + axis.p2c(tick.v) - axis.labelWidth/2); - if (axis.position == "bottom") - pos.top = box.top + box.padding; - else - pos.bottom = canvasHeight - (box.top + box.height - box.padding); - } - else { - pos.top = Math.round(plotOffset.top + axis.p2c(tick.v) - axis.labelHeight/2); - if (axis.position == "left") { - pos.right = canvasWidth - (box.left + box.width - box.padding) - align = "right"; - } - else { - pos.left = box.left + box.padding; - align = "left"; - } - } - - pos.width = axis.labelWidth; - - var style = ["position:absolute", "text-align:" + align ]; - for (var a in pos) - style.push(a + ":" + pos[a] + "px") - - html.push('<div class="tickLabel" style="' + style.join(';') + '">' + tick.label + '</div>'); - } - html.push('</div>'); - } - - html.push('</div>'); - - placeholder.append(html.join("")); - } - - function drawSeries(series) { - if (series.lines.show) - drawSeriesLines(series); - if (series.bars.show) - drawSeriesBars(series); - if (series.points.show) - drawSeriesPoints(series); - } - - function drawSeriesLines(series) { - function plotLine(datapoints, xoffset, yoffset, axisx, axisy) { - var points = datapoints.points, - ps = datapoints.pointsize, - prevx = null, prevy = null; - - ctx.beginPath(); - for (var i = ps; i < points.length; i += ps) { - var x1 = points[i - ps], y1 = points[i - ps + 1], - x2 = points[i], y2 = points[i + 1]; - - if (x1 == null || x2 == null) - continue; - - // clip with ymin - if (y1 <= y2 && y1 < axisy.min) { - if (y2 < axisy.min) - continue; // line segment is outside - // compute new intersection point - x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; - y1 = axisy.min; - } - else if (y2 <= y1 && y2 < axisy.min) { - if (y1 < axisy.min) - continue; - x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; - y2 = axisy.min; - } - - // clip with ymax - if (y1 >= y2 && y1 > axisy.max) { - if (y2 > axisy.max) - continue; - x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; - y1 = axisy.max; - } - else if (y2 >= y1 && y2 > axisy.max) { - if (y1 > axisy.max) - continue; - x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; - y2 = axisy.max; - } - - // clip with xmin - if (x1 <= x2 && x1 < axisx.min) { - if (x2 < axisx.min) - continue; - y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; - x1 = axisx.min; - } - else if (x2 <= x1 && x2 < axisx.min) { - if (x1 < axisx.min) - continue; - y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; - x2 = axisx.min; - } - - // clip with xmax - if (x1 >= x2 && x1 > axisx.max) { - if (x2 > axisx.max) - continue; - y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; - x1 = axisx.max; - } - else if (x2 >= x1 && x2 > axisx.max) { - if (x1 > axisx.max) - continue; - y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; - x2 = axisx.max; - } - - if (x1 != prevx || y1 != prevy) - ctx.moveTo(axisx.p2c(x1) + xoffset, axisy.p2c(y1) + yoffset); - - prevx = x2; - prevy = y2; - ctx.lineTo(axisx.p2c(x2) + xoffset, axisy.p2c(y2) + yoffset); - } - ctx.stroke(); - } - - function plotLineArea(datapoints, axisx, axisy) { - var points = datapoints.points, - ps = datapoints.pointsize, - bottom = Math.min(Math.max(0, axisy.min), axisy.max), - i = 0, top, areaOpen = false, - ypos = 1, segmentStart = 0, segmentEnd = 0; - - // we process each segment in two turns, first forward - // direction to sketch out top, then once we hit the - // end we go backwards to sketch the bottom - while (true) { - if (ps > 0 && i > points.length + ps) - break; - - i += ps; // ps is negative if going backwards - - var x1 = points[i - ps], - y1 = points[i - ps + ypos], - x2 = points[i], y2 = points[i + ypos]; - - if (areaOpen) { - if (ps > 0 && x1 != null && x2 == null) { - // at turning point - segmentEnd = i; - ps = -ps; - ypos = 2; - continue; - } - - if (ps < 0 && i == segmentStart + ps) { - // done with the reverse sweep - ctx.fill(); - areaOpen = false; - ps = -ps; - ypos = 1; - i = segmentStart = segmentEnd + ps; - continue; - } - } - - if (x1 == null || x2 == null) - continue; - - // clip x values - - // clip with xmin - if (x1 <= x2 && x1 < axisx.min) { - if (x2 < axisx.min) - continue; - y1 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; - x1 = axisx.min; - } - else if (x2 <= x1 && x2 < axisx.min) { - if (x1 < axisx.min) - continue; - y2 = (axisx.min - x1) / (x2 - x1) * (y2 - y1) + y1; - x2 = axisx.min; - } - - // clip with xmax - if (x1 >= x2 && x1 > axisx.max) { - if (x2 > axisx.max) - continue; - y1 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; - x1 = axisx.max; - } - else if (x2 >= x1 && x2 > axisx.max) { - if (x1 > axisx.max) - continue; - y2 = (axisx.max - x1) / (x2 - x1) * (y2 - y1) + y1; - x2 = axisx.max; - } - - if (!areaOpen) { - // open area - ctx.beginPath(); - ctx.moveTo(axisx.p2c(x1), axisy.p2c(bottom)); - areaOpen = true; - } - - // now first check the case where both is outside - if (y1 >= axisy.max && y2 >= axisy.max) { - ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.max)); - ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.max)); - continue; - } - else if (y1 <= axisy.min && y2 <= axisy.min) { - ctx.lineTo(axisx.p2c(x1), axisy.p2c(axisy.min)); - ctx.lineTo(axisx.p2c(x2), axisy.p2c(axisy.min)); - continue; - } - - // else it's a bit more complicated, there might - // be a flat maxed out rectangle first, then a - // triangular cutout or reverse; to find these - // keep track of the current x values - var x1old = x1, x2old = x2; - - // clip the y values, without shortcutting, we - // go through all cases in turn - - // clip with ymin - if (y1 <= y2 && y1 < axisy.min && y2 >= axisy.min) { - x1 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; - y1 = axisy.min; - } - else if (y2 <= y1 && y2 < axisy.min && y1 >= axisy.min) { - x2 = (axisy.min - y1) / (y2 - y1) * (x2 - x1) + x1; - y2 = axisy.min; - } - - // clip with ymax - if (y1 >= y2 && y1 > axisy.max && y2 <= axisy.max) { - x1 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; - y1 = axisy.max; - } - else if (y2 >= y1 && y2 > axisy.max && y1 <= axisy.max) { - x2 = (axisy.max - y1) / (y2 - y1) * (x2 - x1) + x1; - y2 = axisy.max; - } - - // if the x value was changed we got a rectangle - // to fill - if (x1 != x1old) { - ctx.lineTo(axisx.p2c(x1old), axisy.p2c(y1)); - // it goes to (x1, y1), but we fill that below - } - - // fill triangular section, this sometimes result - // in redundant points if (x1, y1) hasn't changed - // from previous line to, but we just ignore that - ctx.lineTo(axisx.p2c(x1), axisy.p2c(y1)); - ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); - - // fill the other rectangle if it's there - if (x2 != x2old) { - ctx.lineTo(axisx.p2c(x2), axisy.p2c(y2)); - ctx.lineTo(axisx.p2c(x2old), axisy.p2c(y2)); - } - } - } - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - ctx.lineJoin = "round"; - - var lw = series.lines.lineWidth, - sw = series.shadowSize; - // FIXME: consider another form of shadow when filling is turned on - if (lw > 0 && sw > 0) { - // draw shadow as a thick and thin line with transparency - ctx.lineWidth = sw; - ctx.strokeStyle = "rgba(0,0,0,0.1)"; - // position shadow at angle from the mid of line - var angle = Math.PI/18; - plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/2), Math.cos(angle) * (lw/2 + sw/2), series.xaxis, series.yaxis); - ctx.lineWidth = sw/2; - plotLine(series.datapoints, Math.sin(angle) * (lw/2 + sw/4), Math.cos(angle) * (lw/2 + sw/4), series.xaxis, series.yaxis); - } - - ctx.lineWidth = lw; - ctx.strokeStyle = series.color; - var fillStyle = getFillStyle(series.lines, series.color, 0, plotHeight); - if (fillStyle) { - ctx.fillStyle = fillStyle; - plotLineArea(series.datapoints, series.xaxis, series.yaxis); - } - - if (lw > 0) - plotLine(series.datapoints, 0, 0, series.xaxis, series.yaxis); - ctx.restore(); - } - - function drawSeriesPoints(series) { - function plotPoints(datapoints, radius, fillStyle, offset, shadow, axisx, axisy, symbol) { - var points = datapoints.points, ps = datapoints.pointsize; - - for (var i = 0; i < points.length; i += ps) { - var x = points[i], y = points[i + 1]; - if (x == null || x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) - continue; - - ctx.beginPath(); - x = axisx.p2c(x); - y = axisy.p2c(y) + offset; - if (symbol == "circle") - ctx.arc(x, y, radius, 0, shadow ? Math.PI : Math.PI * 2, false); - else - symbol(ctx, x, y, radius, shadow); - ctx.closePath(); - - if (fillStyle) { - ctx.fillStyle = fillStyle; - ctx.fill(); - } - ctx.stroke(); - } - } - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - var lw = series.points.lineWidth, - sw = series.shadowSize, - radius = series.points.radius, - symbol = series.points.symbol; - if (lw > 0 && sw > 0) { - // draw shadow in two steps - var w = sw / 2; - ctx.lineWidth = w; - ctx.strokeStyle = "rgba(0,0,0,0.1)"; - plotPoints(series.datapoints, radius, null, w + w/2, true, - series.xaxis, series.yaxis, symbol); - - ctx.strokeStyle = "rgba(0,0,0,0.2)"; - plotPoints(series.datapoints, radius, null, w/2, true, - series.xaxis, series.yaxis, symbol); - } - - ctx.lineWidth = lw; - ctx.strokeStyle = series.color; - plotPoints(series.datapoints, radius, - getFillStyle(series.points, series.color), 0, false, - series.xaxis, series.yaxis, symbol); - ctx.restore(); - } - - function drawBar(x, y, b, barLeft, barRight, offset, fillStyleCallback, axisx, axisy, c, horizontal, lineWidth) { - var left, right, bottom, top, - drawLeft, drawRight, drawTop, drawBottom, - tmp; - - // in horizontal mode, we start the bar from the left - // instead of from the bottom so it appears to be - // horizontal rather than vertical - if (horizontal) { - drawBottom = drawRight = drawTop = true; - drawLeft = false; - left = b; - right = x; - top = y + barLeft; - bottom = y + barRight; - - // account for negative bars - if (right < left) { - tmp = right; - right = left; - left = tmp; - drawLeft = true; - drawRight = false; - } - } - else { - drawLeft = drawRight = drawTop = true; - drawBottom = false; - left = x + barLeft; - right = x + barRight; - bottom = b; - top = y; - - // account for negative bars - if (top < bottom) { - tmp = top; - top = bottom; - bottom = tmp; - drawBottom = true; - drawTop = false; - } - } - - // clip - if (right < axisx.min || left > axisx.max || - top < axisy.min || bottom > axisy.max) - return; - - if (left < axisx.min) { - left = axisx.min; - drawLeft = false; - } - - if (right > axisx.max) { - right = axisx.max; - drawRight = false; - } - - if (bottom < axisy.min) { - bottom = axisy.min; - drawBottom = false; - } - - if (top > axisy.max) { - top = axisy.max; - drawTop = false; - } - - left = axisx.p2c(left); - bottom = axisy.p2c(bottom); - right = axisx.p2c(right); - top = axisy.p2c(top); - - // fill the bar - if (fillStyleCallback) { - c.beginPath(); - c.moveTo(left, bottom); - c.lineTo(left, top); - c.lineTo(right, top); - c.lineTo(right, bottom); - c.fillStyle = fillStyleCallback(bottom, top); - c.fill(); - } - - // draw outline - if (lineWidth > 0 && (drawLeft || drawRight || drawTop || drawBottom)) { - c.beginPath(); - - // FIXME: inline moveTo is buggy with excanvas - c.moveTo(left, bottom + offset); - if (drawLeft) - c.lineTo(left, top + offset); - else - c.moveTo(left, top + offset); - if (drawTop) - c.lineTo(right, top + offset); - else - c.moveTo(right, top + offset); - if (drawRight) - c.lineTo(right, bottom + offset); - else - c.moveTo(right, bottom + offset); - if (drawBottom) - c.lineTo(left, bottom + offset); - else - c.moveTo(left, bottom + offset); - c.stroke(); - } - } - - function drawSeriesBars(series) { - function plotBars(datapoints, barLeft, barRight, offset, fillStyleCallback, axisx, axisy) { - var points = datapoints.points, ps = datapoints.pointsize; - - for (var i = 0; i < points.length; i += ps) { - if (points[i] == null) - continue; - drawBar(points[i], points[i + 1], points[i + 2], barLeft, barRight, offset, fillStyleCallback, axisx, axisy, ctx, series.bars.horizontal, series.bars.lineWidth); - } - } - - ctx.save(); - ctx.translate(plotOffset.left, plotOffset.top); - - // FIXME: figure out a way to add shadows (for instance along the right edge) - ctx.lineWidth = series.bars.lineWidth; - ctx.strokeStyle = series.color; - var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; - var fillStyleCallback = series.bars.fill ? function (bottom, top) { return getFillStyle(series.bars, series.color, bottom, top); } : null; - plotBars(series.datapoints, barLeft, barLeft + series.bars.barWidth, 0, fillStyleCallback, series.xaxis, series.yaxis); - ctx.restore(); - } - - function getFillStyle(filloptions, seriesColor, bottom, top) { - var fill = filloptions.fill; - if (!fill) - return null; - - if (filloptions.fillColor) - return getColorOrGradient(filloptions.fillColor, bottom, top, seriesColor); - - var c = $.color.parse(seriesColor); - c.a = typeof fill == "number" ? fill : 0.4; - c.normalize(); - return c.toString(); - } - - function insertLegend() { - placeholder.find(".legend").remove(); - - if (!options.legend.show) - return; - - var fragments = [], rowStarted = false, - lf = options.legend.labelFormatter, s, label; - for (var i = 0; i < series.length; ++i) { - s = series[i]; - label = s.label; - if (!label) - continue; - - if (i % options.legend.noColumns == 0) { - if (rowStarted) - fragments.push('</tr>'); - fragments.push('<tr>'); - rowStarted = true; - } - - if (lf) - label = lf(label, s); - - fragments.push( - '<td class="legendColorBox"><div style="border:1px solid ' + options.legend.labelBoxBorderColor + ';padding:1px"><div style="width:4px;height:0;border:5px solid ' + s.color + ';overflow:hidden"></div></div></td>' + - '<td class="legendLabel">' + label + '</td>'); - } - if (rowStarted) - fragments.push('</tr>'); - - if (fragments.length == 0) - return; - - var table = '<table style="font-size:smaller;color:' + options.grid.color + '">' + fragments.join("") + '</table>'; - if (options.legend.container != null) - $(options.legend.container).html(table); - else { - var pos = "", - p = options.legend.position, - m = options.legend.margin; - if (m[0] == null) - m = [m, m]; - if (p.charAt(0) == "n") - pos += 'top:' + (m[1] + plotOffset.top) + 'px;'; - else if (p.charAt(0) == "s") - pos += 'bottom:' + (m[1] + plotOffset.bottom) + 'px;'; - if (p.charAt(1) == "e") - pos += 'right:' + (m[0] + plotOffset.right) + 'px;'; - else if (p.charAt(1) == "w") - pos += 'left:' + (m[0] + plotOffset.left) + 'px;'; - var legend = $('<div class="legend">' + table.replace('style="', 'style="position:absolute;' + pos +';') + '</div>').appendTo(placeholder); - if (options.legend.backgroundOpacity != 0.0) { - // put in the transparent background - // separately to avoid blended labels and - // label boxes - var c = options.legend.backgroundColor; - if (c == null) { - c = options.grid.backgroundColor; - if (c && typeof c == "string") - c = $.color.parse(c); - else - c = $.color.extract(legend, 'background-color'); - c.a = 1; - c = c.toString(); - } - var div = legend.children(); - $('<div style="position:absolute;width:' + div.width() + 'px;height:' + div.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').prependTo(legend).css('opacity', options.legend.backgroundOpacity); - } - } - } - - - // interactive features - - var highlights = [], - redrawTimeout = null; - - // returns the data item the mouse is over, or null if none is found - function findNearbyItem(mouseX, mouseY, seriesFilter) { - var maxDistance = options.grid.mouseActiveRadius, - smallestDistance = maxDistance * maxDistance + 1, - item = null, foundPoint = false, i, j; - - for (i = series.length - 1; i >= 0; --i) { - if (!seriesFilter(series[i])) - continue; - - var s = series[i], - axisx = s.xaxis, - axisy = s.yaxis, - points = s.datapoints.points, - ps = s.datapoints.pointsize, - mx = axisx.c2p(mouseX), // precompute some stuff to make the loop faster - my = axisy.c2p(mouseY), - maxx = maxDistance / axisx.scale, - maxy = maxDistance / axisy.scale; - - // with inverse transforms, we can't use the maxx/maxy - // optimization, sadly - if (axisx.options.inverseTransform) - maxx = Number.MAX_VALUE; - if (axisy.options.inverseTransform) - maxy = Number.MAX_VALUE; - - if (s.lines.show || s.points.show) { - for (j = 0; j < points.length; j += ps) { - var x = points[j], y = points[j + 1]; - if (x == null) - continue; - - // For points and lines, the cursor must be within a - // certain distance to the data point - if (x - mx > maxx || x - mx < -maxx || - y - my > maxy || y - my < -maxy) - continue; - - // We have to calculate distances in pixels, not in - // data units, because the scales of the axes may be different - var dx = Math.abs(axisx.p2c(x) - mouseX), - dy = Math.abs(axisy.p2c(y) - mouseY), - dist = dx * dx + dy * dy; // we save the sqrt - - // use <= to ensure last point takes precedence - // (last generally means on top of) - if (dist < smallestDistance) { - smallestDistance = dist; - item = [i, j / ps]; - } - } - } - - if (s.bars.show && !item) { // no other point can be nearby - var barLeft = s.bars.align == "left" ? 0 : -s.bars.barWidth/2, - barRight = barLeft + s.bars.barWidth; - - for (j = 0; j < points.length; j += ps) { - var x = points[j], y = points[j + 1], b = points[j + 2]; - if (x == null) - continue; - - // for a bar graph, the cursor must be inside the bar - if (series[i].bars.horizontal ? - (mx <= Math.max(b, x) && mx >= Math.min(b, x) && - my >= y + barLeft && my <= y + barRight) : - (mx >= x + barLeft && mx <= x + barRight && - my >= Math.min(b, y) && my <= Math.max(b, y))) - item = [i, j / ps]; - } - } - } - - if (item) { - i = item[0]; - j = item[1]; - ps = series[i].datapoints.pointsize; - - return { datapoint: series[i].datapoints.points.slice(j * ps, (j + 1) * ps), - dataIndex: j, - series: series[i], - seriesIndex: i }; - } - - return null; - } - - function onMouseMove(e) { - if (options.grid.hoverable) - triggerClickHoverEvent("plothover", e, - function (s) { return s["hoverable"] != false; }); - } - - function onMouseLeave(e) { - if (options.grid.hoverable) - triggerClickHoverEvent("plothover", e, - function (s) { return false; }); - } - - function onClick(e) { - triggerClickHoverEvent("plotclick", e, - function (s) { return s["clickable"] != false; }); - } - - // trigger click or hover event (they send the same parameters - // so we share their code) - function triggerClickHoverEvent(eventname, event, seriesFilter) { - var offset = eventHolder.offset(), - canvasX = event.pageX - offset.left - plotOffset.left, - canvasY = event.pageY - offset.top - plotOffset.top, - pos = canvasToAxisCoords({ left: canvasX, top: canvasY }); - - pos.pageX = event.pageX; - pos.pageY = event.pageY; - - var item = findNearbyItem(canvasX, canvasY, seriesFilter); - - if (item) { - // fill in mouse pos for any listeners out there - item.pageX = parseInt(item.series.xaxis.p2c(item.datapoint[0]) + offset.left + plotOffset.left); - item.pageY = parseInt(item.series.yaxis.p2c(item.datapoint[1]) + offset.top + plotOffset.top); - } - - if (options.grid.autoHighlight) { - // clear auto-highlights - for (var i = 0; i < highlights.length; ++i) { - var h = highlights[i]; - if (h.auto == eventname && - !(item && h.series == item.series && - h.point[0] == item.datapoint[0] && - h.point[1] == item.datapoint[1])) - unhighlight(h.series, h.point); - } - - if (item) - highlight(item.series, item.datapoint, eventname); - } - - placeholder.trigger(eventname, [ pos, item ]); - } - - function triggerRedrawOverlay() { - if (!redrawTimeout) - redrawTimeout = setTimeout(drawOverlay, 30); - } - - function drawOverlay() { - redrawTimeout = null; - - // draw highlights - octx.save(); - octx.clearRect(0, 0, canvasWidth, canvasHeight); - octx.translate(plotOffset.left, plotOffset.top); - - var i, hi; - for (i = 0; i < highlights.length; ++i) { - hi = highlights[i]; - - if (hi.series.bars.show) - drawBarHighlight(hi.series, hi.point); - else - drawPointHighlight(hi.series, hi.point); - } - octx.restore(); - - executeHooks(hooks.drawOverlay, [octx]); - } - - function highlight(s, point, auto) { - if (typeof s == "number") - s = series[s]; - - if (typeof point == "number") { - var ps = s.datapoints.pointsize; - point = s.datapoints.points.slice(ps * point, ps * (point + 1)); - } - - var i = indexOfHighlight(s, point); - if (i == -1) { - highlights.push({ series: s, point: point, auto: auto }); - - triggerRedrawOverlay(); - } - else if (!auto) - highlights[i].auto = false; - } - - function unhighlight(s, point) { - if (s == null && point == null) { - highlights = []; - triggerRedrawOverlay(); - } - - if (typeof s == "number") - s = series[s]; - - if (typeof point == "number") - point = s.data[point]; - - var i = indexOfHighlight(s, point); - if (i != -1) { - highlights.splice(i, 1); - - triggerRedrawOverlay(); - } - } - - function indexOfHighlight(s, p) { - for (var i = 0; i < highlights.length; ++i) { - var h = highlights[i]; - if (h.series == s && h.point[0] == p[0] - && h.point[1] == p[1]) - return i; - } - return -1; - } - - function drawPointHighlight(series, point) { - var x = point[0], y = point[1], - axisx = series.xaxis, axisy = series.yaxis; - - if (x < axisx.min || x > axisx.max || y < axisy.min || y > axisy.max) - return; - - var pointRadius = series.points.radius + series.points.lineWidth / 2; - octx.lineWidth = pointRadius; - octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString(); - var radius = 1.5 * pointRadius, - x = axisx.p2c(x), - y = axisy.p2c(y); - - octx.beginPath(); - if (series.points.symbol == "circle") - octx.arc(x, y, radius, 0, 2 * Math.PI, false); - else - series.points.symbol(octx, x, y, radius, false); - octx.closePath(); - octx.stroke(); - } - - function drawBarHighlight(series, point) { - octx.lineWidth = series.bars.lineWidth; - octx.strokeStyle = $.color.parse(series.color).scale('a', 0.5).toString(); - var fillStyle = $.color.parse(series.color).scale('a', 0.5).toString(); - var barLeft = series.bars.align == "left" ? 0 : -series.bars.barWidth/2; - drawBar(point[0], point[1], point[2] || 0, barLeft, barLeft + series.bars.barWidth, - 0, function () { return fillStyle; }, series.xaxis, series.yaxis, octx, series.bars.horizontal, series.bars.lineWidth); - } - - function getColorOrGradient(spec, bottom, top, defaultColor) { - if (typeof spec == "string") - return spec; - else { - // assume this is a gradient spec; IE currently only - // supports a simple vertical gradient properly, so that's - // what we support too - var gradient = ctx.createLinearGradient(0, top, 0, bottom); - - for (var i = 0, l = spec.colors.length; i < l; ++i) { - var c = spec.colors[i]; - if (typeof c != "string") { - var co = $.color.parse(defaultColor); - if (c.brightness != null) - co = co.scale('rgb', c.brightness) - if (c.opacity != null) - co.a *= c.opacity; - c = co.toString(); - } - gradient.addColorStop(i / (l - 1), c); - } - - return gradient; - } - } - } - - $.plot = function(placeholder, data, options) { - //var t0 = new Date(); - var plot = new Plot($(placeholder), data, options, $.plot.plugins); - //(window.console ? console.log : alert)("time used (msecs): " + ((new Date()).getTime() - t0.getTime())); - return plot; - }; - - $.plot.version = "0.7"; - - $.plot.plugins = []; - - // returns a string with the date d formatted according to fmt - $.plot.formatDate = function(d, fmt, monthNames) { - var leftPad = function(n) { - n = "" + n; - return n.length == 1 ? "0" + n : n; - }; - - var r = []; - var escape = false, padNext = false; - var hours = d.getUTCHours(); - var isAM = hours < 12; - if (monthNames == null) - monthNames = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - - if (fmt.search(/%p|%P/) != -1) { - if (hours > 12) { - hours = hours - 12; - } else if (hours == 0) { - hours = 12; - } - } - for (var i = 0; i < fmt.length; ++i) { - var c = fmt.charAt(i); - - if (escape) { - switch (c) { - case 'h': c = "" + hours; break; - case 'H': c = leftPad(hours); break; - case 'M': c = leftPad(d.getUTCMinutes()); break; - case 'S': c = leftPad(d.getUTCSeconds()); break; - case 'd': c = "" + d.getUTCDate(); break; - case 'm': c = "" + (d.getUTCMonth() + 1); break; - case 'y': c = "" + d.getUTCFullYear(); break; - case 'b': c = "" + monthNames[d.getUTCMonth()]; break; - case 'p': c = (isAM) ? ("" + "am") : ("" + "pm"); break; - case 'P': c = (isAM) ? ("" + "AM") : ("" + "PM"); break; - case '0': c = ""; padNext = true; break; - } - if (c && padNext) { - c = leftPad(c); - padNext = false; - } - r.push(c); - if (!padNext) - escape = false; - } - else { - if (c == "%") - escape = true; - else - r.push(c); - } - } - return r.join(""); - }; - - // round to nearby lower multiple of base - function floorInBase(n, base) { - return base * Math.floor(n / base); - } - -})(jQuery); diff --git a/static/js/plugins/flot/jquery.flot.pie.js b/static/js/plugins/flot/jquery.flot.pie.js deleted file mode 100755 index b46c03c..0000000 --- a/static/js/plugins/flot/jquery.flot.pie.js +++ /dev/null @@ -1,750 +0,0 @@ -/* -Flot plugin for rendering pie charts. The plugin assumes the data is -coming is as a single data value for each series, and each of those -values is a positive value or zero (negative numbers don't make -any sense and will cause strange effects). The data values do -NOT need to be passed in as percentage values because it -internally calculates the total and percentages. - -* Created by Brian Medendorp, June 2009 -* Updated November 2009 with contributions from: btburnett3, Anthony Aragues and Xavi Ivars - -* Changes: - 2009-10-22: lineJoin set to round - 2009-10-23: IE full circle fix, donut - 2009-11-11: Added basic hover from btburnett3 - does not work in IE, and center is off in Chrome and Opera - 2009-11-17: Added IE hover capability submitted by Anthony Aragues - 2009-11-18: Added bug fix submitted by Xavi Ivars (issues with arrays when other JS libraries are included as well) - - -Available options are: -series: { - pie: { - show: true/false - radius: 0-1 for percentage of fullsize, or a specified pixel length, or 'auto' - innerRadius: 0-1 for percentage of fullsize or a specified pixel length, for creating a donut effect - startAngle: 0-2 factor of PI used for starting angle (in radians) i.e 3/2 starts at the top, 0 and 2 have the same result - tilt: 0-1 for percentage to tilt the pie, where 1 is no tilt, and 0 is completely flat (nothing will show) - offset: { - top: integer value to move the pie up or down - left: integer value to move the pie left or right, or 'auto' - }, - stroke: { - color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#FFF') - width: integer pixel width of the stroke - }, - label: { - show: true/false, or 'auto' - formatter: a user-defined function that modifies the text/style of the label text - radius: 0-1 for percentage of fullsize, or a specified pixel length - background: { - color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#000') - opacity: 0-1 - }, - threshold: 0-1 for the percentage value at which to hide labels (if they're too small) - }, - combine: { - threshold: 0-1 for the percentage value at which to combine slices (if they're too small) - color: any hexidecimal color value (other formats may or may not work, so best to stick with something like '#CCC'), if null, the plugin will automatically use the color of the first slice to be combined - label: any text value of what the combined slice should be labeled - } - highlight: { - opacity: 0-1 - } - } -} - -More detail and specific examples can be found in the included HTML file. - -*/ - -(function ($) -{ - function init(plot) // this is the "body" of the plugin - { - var canvas = null; - var target = null; - var maxRadius = null; - var centerLeft = null; - var centerTop = null; - var total = 0; - var redraw = true; - var redrawAttempts = 10; - var shrink = 0.95; - var legendWidth = 0; - var processed = false; - var raw = false; - - // interactive variables - var highlights = []; - - // add hook to determine if pie plugin in enabled, and then perform necessary operations - plot.hooks.processOptions.push(checkPieEnabled); - plot.hooks.bindEvents.push(bindEvents); - - // check to see if the pie plugin is enabled - function checkPieEnabled(plot, options) - { - if (options.series.pie.show) - { - //disable grid - options.grid.show = false; - - // set labels.show - if (options.series.pie.label.show=='auto') - if (options.legend.show) - options.series.pie.label.show = false; - else - options.series.pie.label.show = true; - - // set radius - if (options.series.pie.radius=='auto') - if (options.series.pie.label.show) - options.series.pie.radius = 3/4; - else - options.series.pie.radius = 1; - - // ensure sane tilt - if (options.series.pie.tilt>1) - options.series.pie.tilt=1; - if (options.series.pie.tilt<0) - options.series.pie.tilt=0; - - // add processData hook to do transformations on the data - plot.hooks.processDatapoints.push(processDatapoints); - plot.hooks.drawOverlay.push(drawOverlay); - - // add draw hook - plot.hooks.draw.push(draw); - } - } - - // bind hoverable events - function bindEvents(plot, eventHolder) - { - var options = plot.getOptions(); - - if (options.series.pie.show && options.grid.hoverable) - eventHolder.unbind('mousemove').mousemove(onMouseMove); - - if (options.series.pie.show && options.grid.clickable) - eventHolder.unbind('click').click(onClick); - } - - - // debugging function that prints out an object - function alertObject(obj) - { - var msg = ''; - function traverse(obj, depth) - { - if (!depth) - depth = 0; - for (var i = 0; i < obj.length; ++i) - { - for (var j=0; j<depth; j++) - msg += '\t'; - - if( typeof obj[i] == "object") - { // its an object - msg += ''+i+':\n'; - traverse(obj[i], depth+1); - } - else - { // its a value - msg += ''+i+': '+obj[i]+'\n'; - } - } - } - traverse(obj); - alert(msg); - } - - function calcTotal(data) - { - for (var i = 0; i < data.length; ++i) - { - var item = parseFloat(data[i].data[0][1]); - if (item) - total += item; - } - } - - function processDatapoints(plot, series, data, datapoints) - { - if (!processed) - { - processed = true; - - canvas = plot.getCanvas(); - target = $(canvas).parent(); - options = plot.getOptions(); - - plot.setData(combine(plot.getData())); - } - } - - function setupPie() - { - legendWidth = target.children().filter('.legend').children().width(); - - // calculate maximum radius and center point - maxRadius = Math.min(canvas.width,(canvas.height/options.series.pie.tilt))/2; - centerTop = (canvas.height/2)+options.series.pie.offset.top; - centerLeft = (canvas.width/2); - - if (options.series.pie.offset.left=='auto') - if (options.legend.position.match('w')) - centerLeft += legendWidth/2; - else - centerLeft -= legendWidth/2; - else - centerLeft += options.series.pie.offset.left; - - if (centerLeft<maxRadius) - centerLeft = maxRadius; - else if (centerLeft>canvas.width-maxRadius) - centerLeft = canvas.width-maxRadius; - } - - function fixData(data) - { - for (var i = 0; i < data.length; ++i) - { - if (typeof(data[i].data)=='number') - data[i].data = [[1,data[i].data]]; - else if (typeof(data[i].data)=='undefined' || typeof(data[i].data[0])=='undefined') - { - if (typeof(data[i].data)!='undefined' && typeof(data[i].data.label)!='undefined') - data[i].label = data[i].data.label; // fix weirdness coming from flot - data[i].data = [[1,0]]; - - } - } - return data; - } - - function combine(data) - { - data = fixData(data); - calcTotal(data); - var combined = 0; - var numCombined = 0; - var color = options.series.pie.combine.color; - - var newdata = []; - for (var i = 0; i < data.length; ++i) - { - // make sure its a number - data[i].data[0][1] = parseFloat(data[i].data[0][1]); - if (!data[i].data[0][1]) - data[i].data[0][1] = 0; - - if (data[i].data[0][1]/total<=options.series.pie.combine.threshold) - { - combined += data[i].data[0][1]; - numCombined++; - if (!color) - color = data[i].color; - } - else - { - newdata.push({ - data: [[1,data[i].data[0][1]]], - color: data[i].color, - label: data[i].label, - angle: (data[i].data[0][1]*(Math.PI*2))/total, - percent: (data[i].data[0][1]/total*100) - }); - } - } - if (numCombined>0) - newdata.push({ - data: [[1,combined]], - color: color, - label: options.series.pie.combine.label, - angle: (combined*(Math.PI*2))/total, - percent: (combined/total*100) - }); - return newdata; - } - - function draw(plot, newCtx) - { - if (!target) return; // if no series were passed - ctx = newCtx; - - setupPie(); - var slices = plot.getData(); - - var attempts = 0; - while (redraw && attempts<redrawAttempts) - { - redraw = false; - if (attempts>0) - maxRadius *= shrink; - attempts += 1; - clear(); - if (options.series.pie.tilt<=0.8) - drawShadow(); - drawPie(); - } - if (attempts >= redrawAttempts) { - clear(); - target.prepend('<div class="error">Could not draw pie with labels contained inside canvas</div>'); - } - - if ( plot.setSeries && plot.insertLegend ) - { - plot.setSeries(slices); - plot.insertLegend(); - } - - // we're actually done at this point, just defining internal functions at this point - - function clear() - { - ctx.clearRect(0,0,canvas.width,canvas.height); - target.children().filter('.pieLabel, .pieLabelBackground').remove(); - } - - function drawShadow() - { - var shadowLeft = 5; - var shadowTop = 15; - var edge = 10; - var alpha = 0.02; - - // set radius - if (options.series.pie.radius>1) - var radius = options.series.pie.radius; - else - var radius = maxRadius * options.series.pie.radius; - - if (radius>=(canvas.width/2)-shadowLeft || radius*options.series.pie.tilt>=(canvas.height/2)-shadowTop || radius<=edge) - return; // shadow would be outside canvas, so don't draw it - - ctx.save(); - ctx.translate(shadowLeft,shadowTop); - ctx.globalAlpha = alpha; - ctx.fillStyle = '#000'; - - // center and rotate to starting position - ctx.translate(centerLeft,centerTop); - ctx.scale(1, options.series.pie.tilt); - - //radius -= edge; - for (var i=1; i<=edge; i++) - { - ctx.beginPath(); - ctx.arc(0,0,radius,0,Math.PI*2,false); - ctx.fill(); - radius -= i; - } - - ctx.restore(); - } - - function drawPie() - { - startAngle = Math.PI*options.series.pie.startAngle; - - // set radius - if (options.series.pie.radius>1) - var radius = options.series.pie.radius; - else - var radius = maxRadius * options.series.pie.radius; - - // center and rotate to starting position - ctx.save(); - ctx.translate(centerLeft,centerTop); - ctx.scale(1, options.series.pie.tilt); - //ctx.rotate(startAngle); // start at top; -- This doesn't work properly in Opera - - // draw slices - ctx.save(); - var currentAngle = startAngle; - for (var i = 0; i < slices.length; ++i) - { - slices[i].startAngle = currentAngle; - drawSlice(slices[i].angle, slices[i].color, true); - } - ctx.restore(); - - // draw slice outlines - ctx.save(); - ctx.lineWidth = options.series.pie.stroke.width; - currentAngle = startAngle; - for (var i = 0; i < slices.length; ++i) - drawSlice(slices[i].angle, options.series.pie.stroke.color, false); - ctx.restore(); - - // draw donut hole - drawDonutHole(ctx); - - // draw labels - if (options.series.pie.label.show) - drawLabels(); - - // restore to original state - ctx.restore(); - - function drawSlice(angle, color, fill) - { - if (angle<=0) - return; - - if (fill) - ctx.fillStyle = color; - else - { - ctx.strokeStyle = color; - ctx.lineJoin = 'round'; - } - - ctx.beginPath(); - if (Math.abs(angle - Math.PI*2) > 0.000000001) - ctx.moveTo(0,0); // Center of the pie - else if ($.browser.msie) - angle -= 0.0001; - //ctx.arc(0,0,radius,0,angle,false); // This doesn't work properly in Opera - ctx.arc(0,0,radius,currentAngle,currentAngle+angle,false); - ctx.closePath(); - //ctx.rotate(angle); // This doesn't work properly in Opera - currentAngle += angle; - - if (fill) - ctx.fill(); - else - ctx.stroke(); - } - - function drawLabels() - { - var currentAngle = startAngle; - - // set radius - if (options.series.pie.label.radius>1) - var radius = options.series.pie.label.radius; - else - var radius = maxRadius * options.series.pie.label.radius; - - for (var i = 0; i < slices.length; ++i) - { - if (slices[i].percent >= options.series.pie.label.threshold*100) - drawLabel(slices[i], currentAngle, i); - currentAngle += slices[i].angle; - } - - function drawLabel(slice, startAngle, index) - { - if (slice.data[0][1]==0) - return; - - // format label text - var lf = options.legend.labelFormatter, text, plf = options.series.pie.label.formatter; - if (lf) - text = lf(slice.label, slice); - else - text = slice.label; - if (plf) - text = plf(text, slice); - - var halfAngle = ((startAngle+slice.angle) + startAngle)/2; - var x = centerLeft + Math.round(Math.cos(halfAngle) * radius); - var y = centerTop + Math.round(Math.sin(halfAngle) * radius) * options.series.pie.tilt; - - var html = '<span class="pieLabel" id="pieLabel'+index+'" style="position:absolute;top:' + y + 'px;left:' + x + 'px;">' + text + "</span>"; - target.append(html); - var label = target.children('#pieLabel'+index); - var labelTop = (y - label.height()/2); - var labelLeft = (x - label.width()/2); - label.css('top', labelTop); - label.css('left', labelLeft); - - // check to make sure that the label is not outside the canvas - if (0-labelTop>0 || 0-labelLeft>0 || canvas.height-(labelTop+label.height())<0 || canvas.width-(labelLeft+label.width())<0) - redraw = true; - - if (options.series.pie.label.background.opacity != 0) { - // put in the transparent background separately to avoid blended labels and label boxes - var c = options.series.pie.label.background.color; - if (c == null) { - c = slice.color; - } - var pos = 'top:'+labelTop+'px;left:'+labelLeft+'px;'; - $('<div class="pieLabelBackground" style="position:absolute;width:' + label.width() + 'px;height:' + label.height() + 'px;' + pos +'background-color:' + c + ';"> </div>').insertBefore(label).css('opacity', options.series.pie.label.background.opacity); - } - } // end individual label function - } // end drawLabels function - } // end drawPie function - } // end draw function - - // Placed here because it needs to be accessed from multiple locations - function drawDonutHole(layer) - { - // draw donut hole - if(options.series.pie.innerRadius > 0) - { - // subtract the center - layer.save(); - innerRadius = options.series.pie.innerRadius > 1 ? options.series.pie.innerRadius : maxRadius * options.series.pie.innerRadius; - layer.globalCompositeOperation = 'destination-out'; // this does not work with excanvas, but it will fall back to using the stroke color - layer.beginPath(); - layer.fillStyle = options.series.pie.stroke.color; - layer.arc(0,0,innerRadius,0,Math.PI*2,false); - layer.fill(); - layer.closePath(); - layer.restore(); - - // add inner stroke - layer.save(); - layer.beginPath(); - layer.strokeStyle = options.series.pie.stroke.color; - layer.arc(0,0,innerRadius,0,Math.PI*2,false); - layer.stroke(); - layer.closePath(); - layer.restore(); - // TODO: add extra shadow inside hole (with a mask) if the pie is tilted. - } - } - - //-- Additional Interactive related functions -- - - function isPointInPoly(poly, pt) - { - for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) - ((poly[i][1] <= pt[1] && pt[1] < poly[j][1]) || (poly[j][1] <= pt[1] && pt[1]< poly[i][1])) - && (pt[0] < (poly[j][0] - poly[i][0]) * (pt[1] - poly[i][1]) / (poly[j][1] - poly[i][1]) + poly[i][0]) - && (c = !c); - return c; - } - - function findNearbySlice(mouseX, mouseY) - { - var slices = plot.getData(), - options = plot.getOptions(), - radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; - - for (var i = 0; i < slices.length; ++i) - { - var s = slices[i]; - - if(s.pie.show) - { - ctx.save(); - ctx.beginPath(); - ctx.moveTo(0,0); // Center of the pie - //ctx.scale(1, options.series.pie.tilt); // this actually seems to break everything when here. - ctx.arc(0,0,radius,s.startAngle,s.startAngle+s.angle,false); - ctx.closePath(); - x = mouseX-centerLeft; - y = mouseY-centerTop; - if(ctx.isPointInPath) - { - if (ctx.isPointInPath(mouseX-centerLeft, mouseY-centerTop)) - { - //alert('found slice!'); - ctx.restore(); - return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i}; - } - } - else - { - // excanvas for IE doesn;t support isPointInPath, this is a workaround. - p1X = (radius * Math.cos(s.startAngle)); - p1Y = (radius * Math.sin(s.startAngle)); - p2X = (radius * Math.cos(s.startAngle+(s.angle/4))); - p2Y = (radius * Math.sin(s.startAngle+(s.angle/4))); - p3X = (radius * Math.cos(s.startAngle+(s.angle/2))); - p3Y = (radius * Math.sin(s.startAngle+(s.angle/2))); - p4X = (radius * Math.cos(s.startAngle+(s.angle/1.5))); - p4Y = (radius * Math.sin(s.startAngle+(s.angle/1.5))); - p5X = (radius * Math.cos(s.startAngle+s.angle)); - p5Y = (radius * Math.sin(s.startAngle+s.angle)); - arrPoly = [[0,0],[p1X,p1Y],[p2X,p2Y],[p3X,p3Y],[p4X,p4Y],[p5X,p5Y]]; - arrPoint = [x,y]; - // TODO: perhaps do some mathmatical trickery here with the Y-coordinate to compensate for pie tilt? - if(isPointInPoly(arrPoly, arrPoint)) - { - ctx.restore(); - return {datapoint: [s.percent, s.data], dataIndex: 0, series: s, seriesIndex: i}; - } - } - ctx.restore(); - } - } - - return null; - } - - function onMouseMove(e) - { - triggerClickHoverEvent('plothover', e); - } - - function onClick(e) - { - triggerClickHoverEvent('plotclick', e); - } - - // trigger click or hover event (they send the same parameters so we share their code) - function triggerClickHoverEvent(eventname, e) - { - var offset = plot.offset(), - canvasX = parseInt(e.pageX - offset.left), - canvasY = parseInt(e.pageY - offset.top), - item = findNearbySlice(canvasX, canvasY); - - if (options.grid.autoHighlight) - { - // clear auto-highlights - for (var i = 0; i < highlights.length; ++i) - { - var h = highlights[i]; - if (h.auto == eventname && !(item && h.series == item.series)) - unhighlight(h.series); - } - } - - // highlight the slice - if (item) - highlight(item.series, eventname); - - // trigger any hover bind events - var pos = { pageX: e.pageX, pageY: e.pageY }; - target.trigger(eventname, [ pos, item ]); - } - - function highlight(s, auto) - { - if (typeof s == "number") - s = series[s]; - - var i = indexOfHighlight(s); - if (i == -1) - { - highlights.push({ series: s, auto: auto }); - plot.triggerRedrawOverlay(); - } - else if (!auto) - highlights[i].auto = false; - } - - function unhighlight(s) - { - if (s == null) - { - highlights = []; - plot.triggerRedrawOverlay(); - } - - if (typeof s == "number") - s = series[s]; - - var i = indexOfHighlight(s); - if (i != -1) - { - highlights.splice(i, 1); - plot.triggerRedrawOverlay(); - } - } - - function indexOfHighlight(s) - { - for (var i = 0; i < highlights.length; ++i) - { - var h = highlights[i]; - if (h.series == s) - return i; - } - return -1; - } - - function drawOverlay(plot, octx) - { - //alert(options.series.pie.radius); - var options = plot.getOptions(); - //alert(options.series.pie.radius); - - var radius = options.series.pie.radius > 1 ? options.series.pie.radius : maxRadius * options.series.pie.radius; - - octx.save(); - octx.translate(centerLeft, centerTop); - octx.scale(1, options.series.pie.tilt); - - for (i = 0; i < highlights.length; ++i) - drawHighlight(highlights[i].series); - - drawDonutHole(octx); - - octx.restore(); - - function drawHighlight(series) - { - if (series.angle < 0) return; - - //octx.fillStyle = parseColor(options.series.pie.highlight.color).scale(null, null, null, options.series.pie.highlight.opacity).toString(); - octx.fillStyle = "rgba(255, 255, 255, "+options.series.pie.highlight.opacity+")"; // this is temporary until we have access to parseColor - - octx.beginPath(); - if (Math.abs(series.angle - Math.PI*2) > 0.000000001) - octx.moveTo(0,0); // Center of the pie - octx.arc(0,0,radius,series.startAngle,series.startAngle+series.angle,false); - octx.closePath(); - octx.fill(); - } - - } - - } // end init (plugin body) - - // define pie specific options and their default values - var options = { - series: { - pie: { - show: false, - radius: 'auto', // actual radius of the visible pie (based on full calculated radius if <=1, or hard pixel value) - innerRadius:0, /* for donut */ - startAngle: 3/2, - tilt: 1, - offset: { - top: 0, - left: 'auto' - }, - stroke: { - color: '#FFF', - width: 1 - }, - label: { - show: 'auto', - formatter: function(label, slice){ - return '<div style="font-size:x-small;text-align:center;padding:2px;color:'+slice.color+';">'+label+'<br/>'+Math.round(slice.percent)+'%</div>'; - }, // formatter function - radius: 1, // radius at which to place the labels (based on full calculated radius if <=1, or hard pixel value) - background: { - color: null, - opacity: 0 - }, - threshold: 0 // percentage at which to hide the label (i.e. the slice is too narrow) - }, - combine: { - threshold: -1, // percentage at which to combine little slices into one larger slice - color: null, // color to give the new slice (auto-generated if null) - label: 'Other' // label to give the new slice - }, - highlight: { - //color: '#FFF', // will add this functionality once parseColor is available - opacity: 0.5 - } - } - } - }; - - $.plot.plugins.push({ - init: init, - options: options, - name: "pie", - version: "1.0" - }); -})(jQuery); diff --git a/static/js/plugins/flot/jquery.flot.resize.js b/static/js/plugins/flot/jquery.flot.resize.js deleted file mode 100755 index 1178425..0000000 --- a/static/js/plugins/flot/jquery.flot.resize.js +++ /dev/null @@ -1,60 +0,0 @@ -/* Flot plugin for automatically redrawing plots as the placeholder resizes. - -Copyright (c) 2007-2013 IOLA and Ole Laursen. -Licensed under the MIT license. - -It works by listening for changes on the placeholder div (through the jQuery -resize event plugin) - if the size changes, it will redraw the plot. - -There are no options. If you need to disable the plugin for some plots, you -can just fix the size of their placeholders. - -*/ - -/* Inline dependency: - * jQuery resize event - v1.1 - 3/14/2010 - * http://benalman.com/projects/jquery-resize-plugin/ - * - * Copyright (c) 2010 "Cowboy" Ben Alman - * Dual licensed under the MIT and GPL licenses. - * http://benalman.com/about/license/ - */ - -(function($,h,c){var a=$([]),e=$.resize=$.extend($.resize,{}),i,k="setTimeout",j="resize",d=j+"-special-event",b="delay",f="throttleWindow";e[b]=250;e[f]=true;$.event.special[j]={setup:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.add(l);$.data(this,d,{w:l.width(),h:l.height()});if(a.length===1){g()}},teardown:function(){if(!e[f]&&this[k]){return false}var l=$(this);a=a.not(l);l.removeData(d);if(!a.length){clearTimeout(i)}},add:function(l){if(!e[f]&&this[k]){return false}var n;function m(s,o,p){var q=$(this),r=$.data(this,d);r.w=o!==c?o:q.width();r.h=p!==c?p:q.height();n.apply(this,arguments)}if($.isFunction(l)){n=l;return m}else{n=l.handler;l.handler=m}}};function g(){i=h[k](function(){a.each(function(){var n=$(this),m=n.width(),l=n.height(),o=$.data(this,d);if(m!==o.w||l!==o.h){n.trigger(j,[o.w=m,o.h=l])}});g()},e[b])}})(jQuery,this); - -(function ($) { - var options = { }; // no options - - function init(plot) { - function onResize() { - var placeholder = plot.getPlaceholder(); - - // somebody might have hidden us and we can't plot - // when we don't have the dimensions - if (placeholder.width() == 0 || placeholder.height() == 0) - return; - - plot.resize(); - plot.setupGrid(); - plot.draw(); - } - - function bindEvents(plot, eventHolder) { - plot.getPlaceholder().resize(onResize); - } - - function shutdown(plot, eventHolder) { - plot.getPlaceholder().unbind("resize", onResize); - } - - plot.hooks.bindEvents.push(bindEvents); - plot.hooks.shutdown.push(shutdown); - } - - $.plot.plugins.push({ - init: init, - options: options, - name: 'resize', - version: '1.0' - }); -})(jQuery); \ No newline at end of file diff --git a/static/js/plugins/flot/jquery.flot.tooltip.min.js b/static/js/plugins/flot/jquery.flot.tooltip.min.js deleted file mode 100755 index 09e3bbf..0000000 --- a/static/js/plugins/flot/jquery.flot.tooltip.min.js +++ /dev/null @@ -1,12 +0,0 @@ -/* - * jquery.flot.tooltip - * - * description: easy-to-use tooltips for Flot charts - * version: 0.6.2 - * author: Krzysztof Urbas @krzysu [myviews.pl] - * website: https://github.com/krzysu/flot.tooltip - * - * build on 2013-09-30 - * released under MIT License, 2012 -*/ -(function(t){var o={tooltip:!1,tooltipOpts:{content:"%s | X: %x | Y: %y",xDateFormat:null,yDateFormat:null,shifts:{x:10,y:20},defaultTheme:!0,onHover:function(){}}},i=function(t){this.tipPosition={x:0,y:0},this.init(t)};i.prototype.init=function(o){function i(t){var o={};o.x=t.pageX,o.y=t.pageY,s.updateTooltipPosition(o)}function e(t,o,i){var e=s.getDomElement();if(i){var n;n=s.stringFormat(s.tooltipOptions.content,i),e.html(n),s.updateTooltipPosition({x:o.pageX,y:o.pageY}),e.css({left:s.tipPosition.x+s.tooltipOptions.shifts.x,top:s.tipPosition.y+s.tooltipOptions.shifts.y}).show(),"function"==typeof s.tooltipOptions.onHover&&s.tooltipOptions.onHover(i,e)}else e.hide().html("")}var s=this;o.hooks.bindEvents.push(function(o,n){s.plotOptions=o.getOptions(),s.plotOptions.tooltip!==!1&&void 0!==s.plotOptions.tooltip&&(s.tooltipOptions=s.plotOptions.tooltipOpts,s.getDomElement(),t(o.getPlaceholder()).bind("plothover",e),t(n).bind("mousemove",i))}),o.hooks.shutdown.push(function(o,s){t(o.getPlaceholder()).unbind("plothover",e),t(s).unbind("mousemove",i)})},i.prototype.getDomElement=function(){var o;return t("#flotTip").length>0?o=t("#flotTip"):(o=t("<div />").attr("id","flotTip"),o.appendTo("body").hide().css({position:"absolute"}),this.tooltipOptions.defaultTheme&&o.css({background:"#fff","z-index":"100",padding:"0.4em 0.6em","border-radius":"0.5em","font-size":"0.8em",border:"1px solid #111",display:"none","white-space":"nowrap"})),o},i.prototype.updateTooltipPosition=function(o){var i=t("#flotTip").outerWidth()+this.tooltipOptions.shifts.x,e=t("#flotTip").outerHeight()+this.tooltipOptions.shifts.y;o.x-t(window).scrollLeft()>t(window).innerWidth()-i&&(o.x-=i),o.y-t(window).scrollTop()>t(window).innerHeight()-e&&(o.y-=e),this.tipPosition.x=o.x,this.tipPosition.y=o.y},i.prototype.stringFormat=function(t,o){var i=/%p\.{0,1}(\d{0,})/,e=/%s/,s=/%x\.{0,1}(?:\d{0,})/,n=/%y\.{0,1}(?:\d{0,})/;return"function"==typeof t&&(t=t(o.series.label,o.series.data[o.dataIndex][0],o.series.data[o.dataIndex][1],o)),o.series.percent!==void 0&&(t=this.adjustValPrecision(i,t,o.series.percent)),o.series.label!==void 0&&(t=t.replace(e,o.series.label)),this.isTimeMode("xaxis",o)&&this.isXDateFormat(o)&&(t=t.replace(s,this.timestampToDate(o.series.data[o.dataIndex][0],this.tooltipOptions.xDateFormat))),this.isTimeMode("yaxis",o)&&this.isYDateFormat(o)&&(t=t.replace(n,this.timestampToDate(o.series.data[o.dataIndex][1],this.tooltipOptions.yDateFormat))),"number"==typeof o.series.data[o.dataIndex][0]&&(t=this.adjustValPrecision(s,t,o.series.data[o.dataIndex][0])),"number"==typeof o.series.data[o.dataIndex][1]&&(t=this.adjustValPrecision(n,t,o.series.data[o.dataIndex][1])),o.series.xaxis.tickFormatter!==void 0&&(t=t.replace(s,o.series.xaxis.tickFormatter(o.series.data[o.dataIndex][0],o.series.xaxis))),o.series.yaxis.tickFormatter!==void 0&&(t=t.replace(n,o.series.yaxis.tickFormatter(o.series.data[o.dataIndex][1],o.series.yaxis))),t},i.prototype.isTimeMode=function(t,o){return o.series[t].options.mode!==void 0&&"time"===o.series[t].options.mode},i.prototype.isXDateFormat=function(){return this.tooltipOptions.xDateFormat!==void 0&&null!==this.tooltipOptions.xDateFormat},i.prototype.isYDateFormat=function(){return this.tooltipOptions.yDateFormat!==void 0&&null!==this.tooltipOptions.yDateFormat},i.prototype.timestampToDate=function(o,i){var e=new Date(o);return t.plot.formatDate(e,i)},i.prototype.adjustValPrecision=function(t,o,i){var e,s=o.match(t);return null!==s&&""!==RegExp.$1&&(e=RegExp.$1,i=i.toFixed(e),o=o.replace(t,i)),o};var e=function(t){new i(t)};t.plot.plugins.push({init:e,options:o,name:"tooltip",version:"0.6.1"})})(jQuery); \ No newline at end of file diff --git a/static/js/spice-html5/spice.css b/static/js/spice-html5/spice.css index 23b7e51..968ba16 100755 --- a/static/js/spice-html5/spice.css +++ b/static/js/spice-html5/spice.css @@ -36,7 +36,6 @@ body #login input { padding: 5px; - background-color: #fAfAfA; border: 1px inset #999999; outline: none; -moz-border-radius: 3px; -webkit-border-radius: 3px; border-radius: 3px; @@ -81,7 +80,7 @@ body { min-height: 600px; height: 100%; - margin: 62px 10px 10px 10px; + margin: 10px; padding: 0; background-color: #333333; } @@ -104,6 +103,8 @@ body -webkit-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.2); -moz-box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.2); box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.2); + /* We default the message box to hidden. */ + display: none; } .spice-message p { margin-bottom: 0em; diff --git a/storages/views.py b/storages/views.py index d57e979..b7f6c25 100644 --- a/storages/views.py +++ b/storages/views.py @@ -105,7 +105,7 @@ def storage(request, compute_id, pool): size, free = conn.get_size() used = (size - free) if state: - percent = (used * 100) / size + percent = (used * 100) // size else: percent = 0 status = conn.get_status() @@ -127,31 +127,31 @@ def storage(request, compute_id, pool): conn.start() return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'stop' in request.POST: try: conn.stop() return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'delete' in request.POST: try: conn.delete() return HttpResponseRedirect(reverse('storages', args=[compute_id])) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'set_autostart' in request.POST: try: conn.set_autostart(1) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'unset_autostart' in request.POST: try: conn.set_autostart(0) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'add_volume' in request.POST: form = AddImage(request.POST) if form.is_valid(): @@ -175,7 +175,7 @@ def storage(request, compute_id, pool): messages.success(request, _('Volume: {} is deleted.'.format(volname))) return HttpResponseRedirect(request.get_full_path()) except libvirtError as lib_err: - error_messages.append(lib_err.message) + error_messages.append(lib_err) if 'iso_upload' in request.POST: if str(request.FILES['file']) in conn.update_volumes(): error_msg = _("ISO image already exist") diff --git a/vrtManager/connection.py b/vrtManager/connection.py index f0b8eb3..9639909 100644 --- a/vrtManager/connection.py +++ b/vrtManager/connection.py @@ -80,7 +80,7 @@ class wvmConnection(object): elif self.type == CONN_SOCKET: self.__connect_socket() else: - raise ValueError('"{type}" is not a valid connection type'.format(type=self.type)) + raise ValueError(f'"{self.type}" is not a valid connection type') if self.connected: # do some preprocessing of the connection: @@ -135,14 +135,14 @@ class wvmConnection(object): def __connect_tcp(self): flags = [libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_PASSPHRASE] auth = [flags, self.__libvirt_auth_credentials_callback, None] - uri = 'qemu+tcp://%s/system' % self.host + uri = f'qemu+tcp://{self.host}/system' try: self.connection = libvirt.openAuth(uri, auth, 0) self.last_error = None except libvirtError as e: - self.last_error = 'Connection Failed: ' + str(e) + self.last_error = f'Connection Failed: {str(e)}' self.connection = None def __connect_ssh(self): @@ -153,7 +153,7 @@ class wvmConnection(object): self.last_error = None except libvirtError as e: - self.last_error = 'Connection Failed: ' + str(e) + ' --- ' + repr(libvirt.virGetLastError()) + self.last_error = f'Connection Failed: {str(e)} --- ' + repr(libvirt.virGetLastError()) self.connection = None def __connect_tls(self): @@ -166,7 +166,7 @@ class wvmConnection(object): self.last_error = None except libvirtError as e: - self.last_error = 'Connection Failed: ' + str(e) + self.last_error = f'Connection Failed: {str(e)}' self.connection = None def __connect_socket(self): @@ -177,7 +177,7 @@ class wvmConnection(object): self.last_error = None except libvirtError as e: - self.last_error = 'Connection Failed: ' + str(e) + self.last_error = f'Connection Failed: {str(e)}' self.connection = None def close(self): @@ -208,18 +208,18 @@ class wvmConnection(object): def __unicode__(self): if self.type == CONN_TCP: - type_str = u'tcp' + type_str = 'tcp' elif self.type == CONN_SSH: - type_str = u'ssh' + type_str = 'ssh' elif self.type == CONN_TLS: - type_str = u'tls' + type_str = 'tls' else: - type_str = u'invalid_type' + type_str = 'invalid_type' - return u'qemu+{type}://{user}@{host}/system'.format(type=type_str, user=self.login, host=self.host) + return f'qemu+{type_str}://{self.login}@{self.host}/system' def __repr__(self): - return '<wvmConnection {connection_str}>'.format(connection_str=unicode(self)) + return f'<wvmConnection {str(self)}>' class wvmConnectionManager(object): @@ -264,9 +264,9 @@ class wvmConnectionManager(object): raises libvirtError if (re)connecting fails """ # force all string values to unicode - host = unicode(host) - login = unicode(login) - passwd = unicode(passwd) if passwd is not None else None + host = str(host) + login = str(login) + passwd = str(passwd) if passwd is not None else None connection = self._search_connection(host, login, passwd, conn) @@ -432,21 +432,21 @@ class wvmConnect(object): def get_version(self): ver = self.wvm.getVersion() - major = ver / 1000000 + major = ver // 1000000 ver = ver % 1000000 - minor = ver / 1000 + minor = ver // 1000 ver = ver % 1000 release = ver - return "%s.%s.%s" % (major, minor, release) + return f"{major}.{minor}.{release}" def get_lib_version(self): ver = self.wvm.getLibVersion() - major = ver / 1000000 + major = ver // 1000000 ver %= 1000000 - minor = ver / 1000 + minor = ver // 1000 ver %= 1000 release = ver - return "%s.%s.%s" % (major,minor,release) + return f"{major}.{minor}.{release}" def is_kvm_supported(self): """Return KVM capabilities.""" diff --git a/vrtManager/create.py b/vrtManager/create.py index 4d0d14e..f4e0faf 100644 --- a/vrtManager/create.py +++ b/vrtManager/create.py @@ -6,9 +6,6 @@ from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_FORMAT from webvirtcloud.settings import INSTANCE_VOLUME_DEFAULT_SCSI_CONTROLLER - - - def get_rbd_storage_data(stg): xml = stg.XMLDesc(0) ceph_user = util.get_xml_path(xml, "/pool/source/auth/@username") @@ -236,10 +233,10 @@ class wvmCreate(wvmConnect): """ xml += """<devices>""" - vd_disk_letters = list(string.lowercase) - fd_disk_letters = list(string.lowercase) - hd_disk_letters = list(string.lowercase) - sd_disk_letters = list(string.lowercase) + vd_disk_letters = list(string.ascii_lowercase) + fd_disk_letters = list(string.ascii_lowercase) + hd_disk_letters = list(string.ascii_lowercase) + sd_disk_letters = list(string.ascii_lowercase) add_cd = True disk_opts = '' diff --git a/vrtManager/hostdetails.py b/vrtManager/hostdetails.py index 6a036e1..9a88853 100644 --- a/vrtManager/hostdetails.py +++ b/vrtManager/hostdetails.py @@ -19,10 +19,10 @@ class wvmHostDetails(wvmConnect): all_mem = self.wvm.getInfo()[1] * 1048576 freemem = self.wvm.getMemoryStats(-1, 0) if type(freemem) == dict: - free = (freemem.values()[0] + - freemem.values()[2] + - freemem.values()[3]) * 1024 - percent = (100 - ((free * 100) / all_mem)) + free = (freemem['buffers'] + + freemem['free'] + + freemem['cached']) * 1024 + percent = abs(100 - ((free * 100) // all_mem)) usage = (all_mem - free) mem_usage = {'total': all_mem, 'usage': usage, 'percent': percent} else: @@ -38,7 +38,7 @@ class wvmHostDetails(wvmConnect): cpu = self.wvm.getCPUStats(-1, 0) if type(cpu) == dict: for num in range(2): - idle = self.wvm.getCPUStats(-1, 0).values()[1] + idle = self.wvm.getCPUStats(-1, 0)['idle'] total = sum(self.wvm.getCPUStats(-1, 0).values()) diff_idle = idle - prev_idle diff_total = total - prev_total diff --git a/vrtManager/instance.py b/vrtManager/instance.py index 275363e..869d577 100644 --- a/vrtManager/instance.py +++ b/vrtManager/instance.py @@ -275,7 +275,7 @@ class wvmInstance(wvmConnect): """Get number of physical CPUs.""" hostinfo = self.wvm.getInfo() pcpus = hostinfo[4] * hostinfo[5] * hostinfo[6] * hostinfo[7] - range_pcpus = xrange(1, int(pcpus + 1)) + range_pcpus = range(1, int(pcpus + 1)) return range_pcpus def get_interface_addresses(self, iface_mac): @@ -322,11 +322,11 @@ class wvmInstance(wvmConnect): return None, None def _get_interface_addresses(self, source): - #("Calling interfaceAddresses source=%s", source) + # ("Calling interfaceAddresses source=%s", source) try: return self.instance.interfaceAddresses(source) except Exception as e: - #log.debug("interfaceAddresses failed: %s", str(e)) + # log.debug("interfaceAddresses failed: %s", str(e)) pass return {} @@ -340,7 +340,7 @@ class wvmInstance(wvmConnect): self._ip_cache["qemuga"] = self._get_interface_addresses( VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_AGENT) - arp_flag = 3 # libvirt."VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP" + arp_flag = 3 # libvirt."VIR_DOMAIN_INTERFACE_ADDRESSES_SRC_ARP" self._ip_cache["arp"] = self._get_interface_addresses(arp_flag) def get_net_devices(self): @@ -501,7 +501,7 @@ class wvmInstance(wvmConnect): else: raise Exception('Unknown boot menu option, please choose one of 0:disable, 1:enable, -1:remove') - xmldom = ElementTree.tostring(tree) + xmldom = ElementTree.tostring(tree).decode() self._defineXML(xmldom) def get_bootorder(self): @@ -592,7 +592,7 @@ class wvmInstance(wvmConnect): d.append(order) else: raise Exception('Invalid Device Type for boot order') - self._defineXML(ElementTree.tostring(tree)) + self._defineXML(ElementTree.tostring(tree).decode()) def mount_iso(self, dev, image): def attach_iso(dev, disk, vol): @@ -618,11 +618,11 @@ class wvmInstance(wvmConnect): if attach_iso(dev, disk, vol): break if self.get_status() == 1: - xml = ElementTree.tostring(disk) + xml = ElementTree.tostring(disk).decode() self.instance.attachDevice(xml) xmldom = self._XMLDesc(VIR_DOMAIN_XML_SECURE) if self.get_status() == 5: - xmldom = ElementTree.tostring(tree) + xmldom = ElementTree.tostring(tree).decode() self._defineXML(xmldom) def umount_iso(self, dev, image): @@ -637,14 +637,14 @@ class wvmInstance(wvmConnect): if elm.get('dev') == dev: disk.remove(src_media) if self.get_status() == 1: - xml_disk = ElementTree.tostring(disk) + xml_disk = ElementTree.tostring(disk).decode() self.instance.attachDevice(xml_disk) xmldom = self._XMLDesc(VIR_DOMAIN_XML_SECURE) if self.get_status() == 5: - xmldom = ElementTree.tostring(tree) + xmldom = ElementTree.tostring(tree).decode() self._defineXML(xmldom) - def attach_disk(self, source, target_dev, target_bus='ide', disk_type='file', + def attach_disk(self, target_dev, source, target_bus='ide', disk_type='file', disk_device='disk', driver_name='qemu', driver_type='raw', readonly=False, shareable=False, serial=None, cache_mode=None, io_mode=None, discard_mode=None, detect_zeroes_mode=None): @@ -683,7 +683,7 @@ class wvmInstance(wvmConnect): tree = etree.fromstring(self._XMLDesc(0)) disk_el = tree.xpath("./devices/disk/target[@dev='{}']".format(target_dev))[0].getparent() - xml_disk = etree.tostring(disk_el) + xml_disk = etree.tostring(disk_el).decode() devices = tree.find('devices') devices.remove(disk_el) @@ -699,6 +699,7 @@ class wvmInstance(wvmConnect): old_disk_type = disk_el.get('type') old_disk_device = disk_el.get('device') old_driver_name = disk_el.xpath('driver/@name')[0] + old_target_bus = disk_el.xpath('target/@bus')[0] additionals = '' if cache_mode is not None and cache_mode != 'default': @@ -715,6 +716,7 @@ class wvmInstance(wvmConnect): xml_disk += "<driver name='%s' type='%s'/>" % (old_driver_name, format) elif old_disk_device == 'disk': xml_disk += "<driver name='%s' type='%s' %s/>" % (old_driver_name, format, additionals) + xml_disk += """<source file='%s'/> <target dev='%s' bus='%s'/>""" % (source, target_dev, target_bus) if readonly: @@ -735,7 +737,7 @@ class wvmInstance(wvmConnect): time.sleep(1) cpu_use_now = self.instance.info()[4] diff_usage = cpu_use_now - cpu_use_ago - cpu_usage['cpu'] = 100 * diff_usage / (1 * nbcore * 10 ** 9L) + cpu_usage['cpu'] = 100 * diff_usage / (1 * nbcore * 10 ** 9) else: cpu_usage['cpu'] = 0 return cpu_usage @@ -746,7 +748,7 @@ class wvmInstance(wvmConnect): def set_vcpu_hotplug(self, status, vcpus_hotplug=0): """ vcpus_hotplug = 0 make all vpus hotpluggable """ vcpus_hotplug = int(self.get_vcpu()) if vcpus_hotplug == 0 else vcpus_hotplug - if self.get_status() == 5: # shutoff + if self.get_status() == 5: # shutoff if status: xml = """ <vcpus>""" xml += """<vcpu id='0' enabled='yes' hotpluggable='no' order='1'/>""" @@ -758,14 +760,14 @@ class wvmInstance(wvmConnect): vcpus = tree.xpath("/domain/vcpus") if not vcpus: tree.append(etree.fromstring(xml)) - self._defineXML(etree.tostring(tree)) + self._defineXML(etree.tostring(tree).decode()) else: tree = etree.fromstring(self._XMLDesc(0)) vcpus = tree.xpath("/domain/vcpus") for vcpu in vcpus: parent = vcpu.getparent() parent.remove(vcpu) - self._defineXML(etree.tostring(tree)) + self._defineXML(etree.tostring(tree).decode()) else: raise libvirtError("Please shutdown the instance then try to enable vCPU hotplug") @@ -892,7 +894,7 @@ class wvmInstance(wvmConnect): listen.attrib.pop("address") except: pass - newxml = ElementTree.tostring(root) + newxml = ElementTree.tostring(root).decode() return self._defineXML(newxml) def get_console_socket(self): @@ -917,7 +919,7 @@ class wvmInstance(wvmConnect): # Little fix for old version ElementTree graphic = root.find("devices/graphics") graphic.set('type', console_type) - newxml = ElementTree.tostring(root) + newxml = ElementTree.tostring(root).decode() self._defineXML(newxml) def get_console_port(self, console_type=None): @@ -953,7 +955,7 @@ class wvmInstance(wvmConnect): graphic.attrib.pop('passwd') except: pass - newxml = ElementTree.tostring(root) + newxml = ElementTree.tostring(root).decode() return self._defineXML(newxml) def set_console_keymap(self, keymap): @@ -972,7 +974,7 @@ class wvmInstance(wvmConnect): graphic.attrib.pop('keymap') except: pass - newxml = ElementTree.tostring(root) + newxml = ElementTree.tostring(root).decode() self._defineXML(newxml) def get_console_keymap(self): @@ -998,7 +1000,7 @@ class wvmInstance(wvmConnect): parent = model.getparent() parent.remove(model) parent.append(etree.fromstring(video_xml)) - self._defineXML(etree.tostring(tree)) + self._defineXML(etree.tostring(tree).decode()) def resize_cpu(self, cur_vcpu, vcpu): """ @@ -1011,11 +1013,11 @@ class wvmInstance(wvmConnect): xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) tree = etree.fromstring(xml) - set_vcpu = tree.find('vcpu') - set_vcpu.text = vcpu - set_vcpu.set('current', cur_vcpu) + vcpu_elem = tree.find('vcpu') + vcpu_elem.text = vcpu + vcpu_elem.set('current', cur_vcpu) - new_xml = etree.tostring(tree) + new_xml = etree.tostring(tree).decode() self._defineXML(new_xml) if is_vcpus_enabled: @@ -1034,14 +1036,14 @@ class wvmInstance(wvmConnect): return xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) - tree = ElementTree.fromstring(xml) + tree = etree.fromstring(xml) - set_mem = tree.find('memory') - set_mem.text = str(memory) - set_cur_mem = tree.find('currentMemory') - set_cur_mem.text = str(cur_memory) + mem_elem = tree.find('memory') + mem_elem.text = str(memory) + cur_mem_elem = tree.find('currentMemory') + cur_mem_elem.text = str(cur_memory) - new_xml = ElementTree.tostring(tree) + new_xml = etree.tostring(tree).decode() self._defineXML(new_xml) def resize_disk(self, disks): @@ -1049,14 +1051,14 @@ class wvmInstance(wvmConnect): Function change disks on vds. """ xml = self._XMLDesc(VIR_DOMAIN_XML_SECURE) - tree = ElementTree.fromstring(xml) + tree = etree.fromstring(xml) for disk in disks: source_dev = disk['path'] vol = self.get_volume_by_path(source_dev) vol.resize(disk['size_new']) - new_xml = ElementTree.tostring(tree) + new_xml = etree.tostring(tree).decode() self._defineXML(new_xml) def get_iso_media(self): @@ -1250,7 +1252,7 @@ class wvmInstance(wvmConnect): 'description': clone_data.get('clone-description', ''), } self._set_options(tree, options) - self._defineXML(ElementTree.tostring(tree)) + self._defineXML(ElementTree.tostring(tree).decode()) return self.get_instance(clone_data['name']).UUIDString() @@ -1297,7 +1299,7 @@ class wvmInstance(wvmConnect): for interface in tree.findall('devices/interface'): source = interface.find('mac') if source.get('address', '') == mac_address: - new_xml = ElementTree.tostring(interface) + new_xml = ElementTree.tostring(interface).decode() if self.get_status() == 1: self.instance.detachDeviceFlags(new_xml, VIR_DOMAIN_AFFECT_LIVE) @@ -1359,7 +1361,7 @@ class wvmInstance(wvmConnect): else: if source is not None: interface.remove(source) - new_xml = ElementTree.tostring(tree) + new_xml = ElementTree.tostring(tree).decode() self._defineXML(new_xml) def set_link_state(self, mac_address, state): @@ -1373,7 +1375,7 @@ class wvmInstance(wvmConnect): link_el = etree.Element("link") link_el.attrib["state"] = state interface.append(link_el) - new_xml = etree.tostring(interface) + new_xml = etree.tostring(interface).decode() if self.get_status() == 1: self.instance.updateDeviceFlags(new_xml, VIR_DOMAIN_AFFECT_LIVE) self.instance.updateDeviceFlags(new_xml, VIR_DOMAIN_AFFECT_CONFIG) @@ -1400,7 +1402,7 @@ class wvmInstance(wvmConnect): tree = ElementTree.fromstring(xml) self._set_options(tree, options) - new_xml = ElementTree.tostring(tree) + new_xml = ElementTree.tostring(tree).decode() self._defineXML(new_xml) def set_memory(self, size, flags=0): @@ -1460,7 +1462,7 @@ class wvmInstance(wvmConnect): parent.append(etree.fromstring(xml)) else: band.append(etree.fromstring(xml)) - new_xml = etree.tostring(tree) + new_xml = etree.tostring(tree).decode() self.wvm.defineXML(new_xml) def unset_qos(self, mac, direction): @@ -1472,7 +1474,7 @@ class wvmInstance(wvmConnect): if parent_mac[0] == mac: band_el.remove(direct) - self.wvm.defineXML(etree.tostring(tree)) + self.wvm.defineXML(etree.tostring(tree).decode()) def add_guest_agent(self): channel_xml = """ @@ -1490,7 +1492,7 @@ class wvmInstance(wvmConnect): tree = etree.fromstring(self._XMLDesc(0)) for target in tree.xpath("/domain/devices/channel[@type='unix']/target[@name='org.qemu.guest_agent.0']"): parent = target.getparent() - channel_xml = etree.tostring(parent) + channel_xml = etree.tostring(parent).decode() if self.get_status() == 1: self.instance.detachDeviceFlags(channel_xml, VIR_DOMAIN_AFFECT_LIVE) self.instance.detachDeviceFlags(channel_xml, VIR_DOMAIN_AFFECT_CONFIG) diff --git a/vrtManager/network.py b/vrtManager/network.py index 560bd42..dafc1e4 100644 --- a/vrtManager/network.py +++ b/vrtManager/network.py @@ -213,7 +213,7 @@ class wvmNetwork(wvmConnect): for host in hosts: ip = host.get('ip') mac = host.get('mac') - name = host.get('name','') + name = host.get('name', '') result.append({'ip': ip, 'mac': mac, 'name': name}) return result else: @@ -223,7 +223,7 @@ class wvmNetwork(wvmConnect): for host in hosts: ip = host.get('ip') id = host.get('id') - name = host.get('name','') + name = host.get('name', '') result.append({'ip': ip, 'id': id, 'name': name}) return result @@ -236,7 +236,7 @@ class wvmNetwork(wvmConnect): range = tree.xpath("./ip[@family='ipv6']/dhcp/range") range[0].set('start', range_start) range[0].set('end', range_end) - self.wvm.networkDefineXML(etree.tostring(tree)) + self.wvm.networkDefineXML(etree.tostring(tree).decode()) def delete_fixed_address(self, ip, family='ipv4'): tree = etree.fromstring(self._XMLDesc(0)) @@ -335,7 +335,7 @@ class wvmNetwork(wvmConnect): parent.append(etree.fromstring(xml)) else: band[0].append(etree.fromstring(xml)) - new_xml = etree.tostring(tree) + new_xml = etree.tostring(tree).decode() self.wvm.networkDefineXML(new_xml) def unset_qos(self, direction): @@ -344,7 +344,7 @@ class wvmNetwork(wvmConnect): parent = direct.getparent() parent.remove(direct) - self.wvm.networkDefineXML(etree.tostring(tree)) + self.wvm.networkDefineXML(etree.tostring(tree).decode()) def edit_network(self, new_xml): self.wvm.networkDefineXML(new_xml) @@ -354,7 +354,7 @@ class wvmNetwork(wvmConnect): self.leases = self.net.DHCPLeases() except Exception as e: self.leases = [] - raise "Error getting %s DHCP leases: %s" % self, str(e) + raise "Error getting %s DHCP leases: %s" % (self, e) def get_dhcp_leases(self): if self.leases is None: diff --git a/vrtManager/nwfilters.py b/vrtManager/nwfilters.py index aeb7e4f..901aa6f 100644 --- a/vrtManager/nwfilters.py +++ b/vrtManager/nwfilters.py @@ -19,7 +19,7 @@ class wvmNWFilters(wvmConnect): tree.set('name', cln_name) uuid = tree.find('uuid') tree.remove(uuid) - self.create_nwfilter(ElementTree.tostring(tree)) + self.create_nwfilter(ElementTree.tostring(tree).decode()) class wvmNWFilter(wvmConnect): @@ -43,7 +43,7 @@ class wvmNWFilter(wvmConnect): tree = ElementTree.fromstring(self._XMLDesc(0)) uuid = tree.find('uuid') tree.remove(uuid) - return ElementTree.tostring(tree) + return ElementTree.tostring(tree).decode() def get_filter_refs(self): refs = [] @@ -64,7 +64,7 @@ class wvmNWFilter(wvmConnect): rule_directives = r.find("./") if rule_directives is not None: - rule_directives = ElementTree.tostring(rule_directives) + rule_directives = ElementTree.tostring(rule_directives).decode() rule_info = { "action": rule_action, @@ -84,7 +84,7 @@ class wvmNWFilter(wvmConnect): if name == ref.get('filter'): tree.remove(ref) break - return ElementTree.tostring(tree) + return ElementTree.tostring(tree).decode() def delete_rule(self, action, direction, priority): tree = ElementTree.fromstring(self._XMLDesc(0)) @@ -93,14 +93,14 @@ class wvmNWFilter(wvmConnect): if rule_tree: tree.remove(rule_tree[0]) - return ElementTree.tostring(tree) + return ElementTree.tostring(tree).decode() def add_ref(self, name): tree = ElementTree.fromstring(self._XMLDesc(0)) element = ElementTree.Element("filterref") element.attrib['filter'] = name tree.append(element) - return ElementTree.tostring(tree) + return ElementTree.tostring(tree).decode() def add_rule(self, xml): tree = ElementTree.fromstring(self._XMLDesc(0)) @@ -122,4 +122,4 @@ class wvmNWFilter(wvmConnect): element.append(rule_directives) tree.append(element) - return ElementTree.tostring(tree) + return ElementTree.tostring(tree).decode() diff --git a/vrtManager/storage.py b/vrtManager/storage.py index bd51b1d..84a5c13 100644 --- a/vrtManager/storage.py +++ b/vrtManager/storage.py @@ -147,13 +147,13 @@ class wvmStorage(wvmConnect): return util.get_xml_path(self._XMLDesc(0), "/pool/target/path") def get_allocation(self): - return long(util.get_xml_path(self._XMLDesc(0), "/pool/allocation")) + return int(util.get_xml_path(self._XMLDesc(0), "/pool/allocation")) def get_available(self): - return long(util.get_xml_path(self._XMLDesc(0), "/pool/available")) + return int(util.get_xml_path(self._XMLDesc(0), "/pool/available")) def get_capacity(self): - return long(util.get_xml_path(self._XMLDesc(0), "/pool/capacity")) + return int(util.get_xml_path(self._XMLDesc(0), "/pool/capacity")) def get_pretty_allocation(self): return util.pretty_bytes(self.get_allocation()) diff --git a/vrtManager/util.py b/vrtManager/util.py index 626269b..ea59881 100644 --- a/vrtManager/util.py +++ b/vrtManager/util.py @@ -34,9 +34,9 @@ def randomUUID(): "%02x" * 6]) % tuple(u) -def randomPasswd(length=12, alphabet=string.letters + string.digits): +def randomPasswd(length=12, alphabet=string.ascii_letters + string.digits): """Generate a random password""" - return ''.join([random.choice(alphabet) for i in xrange(length)]) + return ''.join([random.choice(alphabet) for i in range(length)]) def get_max_vcpus(conn, type=None): @@ -75,7 +75,7 @@ def compareMAC(p, q): else: return -1 - for i in xrange(len(pa)): + for i in range(len(pa)): n = int(pa[i], 0x10) - int(qa[i], 0x10) if n > 0: return 1 @@ -160,12 +160,12 @@ def validate_macaddr(val): if val is None: return - if not (isinstance(val, str) or isinstance(val, basestring)): + if not (isinstance(val, str) or isinstance(val, str)): raise ValueError("MAC address must be a string.") form = re.match("^([0-9a-fA-F]{1,2}:){5}[0-9a-fA-F]{1,2}$", val) if form is None: - raise ValueError("MAC address must be of the format AA:BB:CC:DD:EE:FF, was '%s'" % val) + raise ValueError(f"MAC address must be of the format AA:BB:CC:DD:EE:FF, was {val}") # Mapping of UEFI binary names to their associated architectures. We @@ -189,4 +189,4 @@ uefi_arch_patterns = { "armv7l": [ r".*arm/QEMU_EFI.*", # fedora, gerd's firmware repo ], -} \ No newline at end of file +} diff --git a/webvirtcloud/settings.py.template b/webvirtcloud/settings.py.template index 291c0a3..72871e4 100644 --- a/webvirtcloud/settings.py.template +++ b/webvirtcloud/settings.py.template @@ -4,7 +4,9 @@ Django settings for webvirtcloud project. """ import os -BASE_DIR = os.path.dirname(os.path.dirname(__file__)) + +# Build paths inside the project like this: os.path.join(BASE_DIR, ...) +BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) SECRET_KEY = '' @@ -12,73 +14,44 @@ DEBUG = True ALLOWED_HOSTS = ['*'] -INSTALLED_APPS = ( + +# Application definition + +INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', + 'accounts', 'computes', 'console', - 'networks', - 'storages', - 'interfaces', - 'nwfilters', - 'instances', - 'secrets', - 'logs', - 'accounts', 'create', 'datasource', -) + 'networks', + 'instances', + 'interfaces', + 'nwfilters', + 'storages', + 'secrets', + 'logs', +] -MIDDLEWARE_CLASSES = ( +MIDDLEWARE = [ + 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.RemoteUserMiddleware', - 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', -) - -AUTHENTICATION_BACKENDS = ( - 'django.contrib.auth.backends.ModelBackend', - #'django.contrib.auth.backends.RemoteUserBackend', - #'accounts.backends.MyRemoteUserBackend', -) - -LOGIN_URL = '/accounts/login' + 'django.middleware.locale.LocaleMiddleware', +] ROOT_URLCONF = 'webvirtcloud.urls' -WSGI_APPLICATION = 'webvirtcloud.wsgi.application' - -DATABASES = { - 'default': { - 'ENGINE': 'django.db.backends.sqlite3', - 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), - } -} - -LANGUAGE_CODE = 'en-us' - -TIME_ZONE = 'UTC' - -USE_I18N = True - -USE_L10N = True - -USE_TZ = True - -STATIC_URL = '/static/' - -STATICFILES_DIRS = ( - os.path.join(BASE_DIR, "static"), -) - TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', @@ -95,9 +68,57 @@ TEMPLATES = [ }, ] -## WebVirtCloud settings +WSGI_APPLICATION = 'webvirtcloud.wsgi.application' -# Wobsock port + +# Database +# https://docs.djangoproject.com/en/3.0/ref/settings/#databases + +DATABASES = { + 'default': { + 'ENGINE': 'django.db.backends.sqlite3', + 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'), + } +} + +AUTHENTICATION_BACKENDS = [ + 'django.contrib.auth.backends.ModelBackend', + #'django.contrib.auth.backends.RemoteUserBackend', + #'accounts.backends.MyRemoteUserBackend', +] + +LOGIN_URL = '/accounts/login' + +LANGUAGE_CODE = 'en-us' + +TIME_ZONE = 'UTC' + +USE_I18N = True + +USE_L10N = True + +USE_TZ = True + +STATIC_URL = '/static/' + +STATICFILES_DIRS = [ + os.path.join(BASE_DIR, "static"), +] + +LOGGING = { + "version": 1, + "disable_existing_loggers": False, + "handlers": {"mail_admins": {"level": "ERROR", "class": "django.utils.log.AdminEmailHandler"}}, + "loggers": { + "django.request": {"handlers": ["mail_admins"], "level": "ERROR", "propagate": True} + }, +} + +# +## WebVirtCloud settings +# + +# Websock port WS_PORT = 6080 # Websock host @@ -112,19 +133,19 @@ WS_PUBLIC_HOST = None # Websock SSL connection WS_CERT = None -# list of console types +# List of console types QEMU_CONSOLE_TYPES = ['vnc', 'spice'] -# default console type +# Default console type QEMU_CONSOLE_DEFAULT_TYPE = 'vnc' -# list of console listen addresses +# List of console listen addresses QEMU_CONSOLE_LISTEN_ADDRESSES = ( ('127.0.0.1', 'Localhost'), ('0.0.0.0', 'All interfaces'), ) -# list taken from http://qemu.weilnetz.de/qemu-doc.html#sec_005finvocation +# List taken from http://qemu.weilnetz.de/qemu-doc.html#sec_005finvocation QEMU_KEYMAPS = ['ar', 'da', 'de', 'de-ch', 'en-gb', 'en-us', 'es', 'et', 'fi', 'fo', 'fr', 'fr-be', 'fr-ca', 'fr-ch', 'hr', 'hu', 'is', 'it', 'ja', 'lt', 'lv', 'mk', 'nl', 'nl-be', 'no', 'pl', 'pt', @@ -181,3 +202,9 @@ INSTANCE_CPU_DEFAULT_MODE = 'host-model' # Chipset/Machine: pc or q35 for x86_64 INSTANCE_MACHINE_DEFAULT_TYPE = 'q35' + +# Firmware: BIOS or UEFI for x86_64 +INSTANCE_FIRMWARE_DEFAULT_TYPE = 'BIOS' + +# Architecture: x86_64, i686, etc +INSTANCE_ARCH_DEFAULT_TYPE = 'x86_64' \ No newline at end of file diff --git a/webvirtcloud/urls.py b/webvirtcloud/urls.py index 4924a68..6c21817 100644 --- a/webvirtcloud/urls.py +++ b/webvirtcloud/urls.py @@ -1,17 +1,17 @@ -from django.conf.urls import include, url +from django.urls import include, path from instances.views import index from console.views import console # from django.contrib import admin urlpatterns = [ - url(r'^$', index, name='index'), + path('', index, name='index'), - url(r'^instances/', include('instances.urls')), - url(r'^accounts/', include('accounts.urls')), - url(r'^computes/', include('computes.urls')), - url(r'^logs/', include('logs.urls')), - url(r'^datasource/', include('datasource.urls')), - url(r'^console/$', console, name='console'), - #url(r'^admin/', include(admin.site.urls)), + path('instances/', include('instances.urls')), + path('accounts/', include('accounts.urls')), + path('computes/', include('computes.urls')), + path('logs/', include('logs.urls')), + path('datasource/', include('datasource.urls')), + path('console/', console, name='console'), + # url(r'^admin/', include(admin.site.urls)), ] diff --git a/webvirtcloud/wsgi.py b/webvirtcloud/wsgi.py index 912df99..aafa04f 100644 --- a/webvirtcloud/wsgi.py +++ b/webvirtcloud/wsgi.py @@ -4,11 +4,11 @@ WSGI config for webvirtcloud project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/1.11/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/ """ import os -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webvirtcloud.settings") +os.environ["DJANGO_SETTINGS_MODULE"] = "webvirtcloud.settings" from django.core.wsgi import get_wsgi_application application = get_wsgi_application() diff --git a/webvirtcloud/wsgi_custom.py b/webvirtcloud/wsgi_custom.py index a9bf44c..0abf5da 100644 --- a/webvirtcloud/wsgi_custom.py +++ b/webvirtcloud/wsgi_custom.py @@ -4,14 +4,17 @@ WSGI config for webvirtcloud project. It exposes the WSGI callable as a module-level variable named ``application``. For more information on this file, see -https://docs.djangoproject.com/en/1.7/howto/deployment/wsgi/ +https://docs.djangoproject.com/en/2.0/howto/deployment/wsgi/ """ - -execfile('/srv/webvirtcloud/venv/bin/activate_this.py', dict(__file__='/srv/webvirtcloud/venv/bin/activate_this.py')) - import os, sys -sys.path.append('/srv/webvirtcloud') -os.environ.setdefault("DJANGO_SETTINGS_MODULE", "webvirtcloud.settings") - from django.core.wsgi import get_wsgi_application + +# execfile('/srv/webvirtcloud/venv/bin/activate_this.py', dict(__file__='/srv/webvvirtcloud/venv/bin/activate_this.py')) +exec(compile(open('/srv/webvirtcloud/venv/bin/activate_this.py', "rb").read(), + '/srv/webvirtcloud/venv/bin/activate_this.py', 'exec')) + +sys.path.append('/srv/webvirtcloud') +os.environ["DJANGO_SETTINGS_MODULE"] = "webvirtcloud.settings" + + application = get_wsgi_application()